Skip to content

Instantly share code, notes, and snippets.

@gdog2u
Created December 8, 2021 23:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gdog2u/f0385cdb76c63eb37f274c5603455844 to your computer and use it in GitHub Desktop.
Save gdog2u/f0385cdb76c63eb37f274c5603455844 to your computer and use it in GitHub Desktop.
#!/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