Created
December 8, 2021 23:30
-
-
Save gdog2u/f0385cdb76c63eb37f274c5603455844 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/perl | |
use warnings; | |
use strict; | |
##### | |
# Solution works for demo, but not for input | |
##### | |
our @inputs = get_inputs(); | |
# Cache the first most common bit | |
my $first_mcb = find_mcb_in_position(0); | |
my $o2_gen_rate = find_o2_gen_rate($first_mcb, 1, \@inputs); | |
my $co2_scrub_rate = find_co2_scrub_rate($first_mcb ^ 0b1, 1, \@inputs); | |
# Print solution | |
# debug($o2_gen_rate); | |
# debug($co2_scrub_rate); | |
print $o2_gen_rate * $co2_scrub_rate; | |
sub find_o2_gen_rate | |
{ | |
my $query = $_[0]; | |
my $current_bit = $_[1]; | |
my @search_space = @{ $_[2] }; | |
if(scalar @search_space == 1){ return oct "0b".$search_space[0]; } | |
elsif(scalar @search_space == 0){ die "Uh oh, you made a fucky wucky\n\tLast \$query: $query\n"; } | |
my $mcb = find_mcb_in_position($current_bit, \@search_space); | |
$query .= $mcb; | |
@search_space = grep(/^$query/, @search_space); | |
return find_o2_gen_rate($query, ++$current_bit, \@search_space); | |
} | |
sub find_co2_scrub_rate | |
{ | |
my $query = $_[0]; | |
my $current_bit = $_[1]; | |
my @search_space = @{ $_[2] }; | |
if(scalar @search_space == 1){ return oct "0b".$search_space[0]; } | |
elsif(scalar @search_space == 0){ die "Uh oh, you made a fucky wucky\n\tLast \$query: $query\n"; } | |
my $mcb = find_mcb_in_position($current_bit, \@search_space); | |
$query .= $mcb ^ 0b1; | |
@search_space = grep(/^$query/, @search_space); | |
return find_co2_scrub_rate($query, ++$current_bit, \@search_space); | |
} | |
# Find the most common bit at a given index of an array of bytes | |
sub find_mcb_in_position | |
{ | |
my $index = $_[0]; | |
my @search_space; | |
if(defined($_[1])) | |
{ | |
@search_space = @{ $_[1] }; | |
} | |
else | |
{ | |
@search_space = @inputs; | |
} | |
my $word_length = length $search_space[0]; | |
my $low = 0; | |
my $high = 0; | |
foreach my $word (@search_space) | |
{ | |
my $current_bit = substr($word, $index, 1); | |
if($current_bit eq '0'){ $low++; } | |
else{ $high++; } | |
} | |
return $high == $low ? clamp($high) : clamp($high - $low); | |
} | |
print "\n"; | |
# Load the puzzle inputs into an array | |
# Loads the inputs from the file name supplied as first parameter | |
sub get_inputs | |
{ | |
if(!$ARGV[0]) | |
{ | |
die "Supply path to inputs"; | |
} | |
my @lines; | |
open(my $fh, '<', $ARGV[0]) or die "Failed to open file: $ARGV[0]"; | |
while(my $line = <$fh>) | |
{ | |
chomp $line; | |
push(@lines, $line); | |
} | |
return @lines; | |
} | |
# Return a value clamped between a minimum & a maximum | |
sub clamp | |
{ | |
my $value = $_[0]; | |
my $min = $_[1] || 0; | |
my $max = $_[2] || 1; | |
if($value < $min){ return $min; } | |
if($value > $max){ return $max; } | |
return $value; | |
} | |
1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment