summaryrefslogtreecommitdiff
path: root/7.pl
blob: e671692c9ed78b48a8da596633e3e9ba0a09cb32 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#!/usr/bin/perl
use strict;
use warnings;

# use Data::Dumper;

my @numberss;
my @results;
my $result_sum = 0;
my $result_sum_part_two = 0;

open(my $fh, "7-input.txt") or die;
while (<$fh>) {
  chomp;
  $_ =~ /^(\d+):\s(.*)$/;
  push @results, $1;
  push @numberss, [split /\s/, $2];
}
close($fh);

my $ffffffffffffff = -1;
foreach my $result (@results) {
  $ffffffffffffff++;
  my $numbers = $numberss[$ffffffffffffff];
  my @possible_operations_part_one = combinations(['+', '*'], scalar @$numbers-1);
  my @possible_operations_part_two = combinations(['+', '*', '|'], scalar @$numbers-1);

  my @op_list_base;
  foreach (0..scalar @$numbers-1) {
    if ($_ == 0) { $op_list_base[$_] = $numbers->[$_]; }
    else { $op_list_base[$_+$_] = $numbers->[$_]; }
  }

  my @to_calculate_part_one;
  foreach my $operation_symbol (@possible_operations_part_one) {
    my @op_list = @op_list_base;
    my $symbol_idx = 0;
    foreach (0..scalar @op_list-1) {
      if (not defined $op_list[$_]) {
        $op_list[$_] = $operation_symbol->[$symbol_idx];
        $symbol_idx++;
      }
    }
    push @to_calculate_part_one, \@op_list;
  }

  my @to_calculate_part_two;
  foreach my $operation_symbol (@possible_operations_part_two) {
    my @op_list = @op_list_base;
    my $symbol_idx = 0;
    foreach (0..scalar @op_list-1) {
      if (not defined $op_list[$_]) {
        $op_list[$_] = $operation_symbol->[$symbol_idx];
        $symbol_idx++;
      }
    }
    # print Dumper(\@op_list);
    push @to_calculate_part_two, \@op_list;
  }

  foreach (0..scalar@to_calculate_part_one-1) {
    if (calculate($to_calculate_part_one[$_]) == $result) {
      $result_sum=$result_sum+$result;
      print "puzzle 1: $result ok\n";
      last;
    }
  }

  foreach (0..scalar@to_calculate_part_two-1) {
    if (calculate($to_calculate_part_two[$_]) == $result) {
      $result_sum_part_two=$result_sum_part_two+$result;
      print "puzzle 2: $result ok\n";
      last;
    }
  }
}

print "puzzle 1: $result_sum\n";
print "puzzle 2: $result_sum_part_two\n";

sub calculate {
  my $expression = shift;
  my @local_expression = @$expression;

  while (scalar @local_expression > 1) {
    for(my $o=1; $o <= scalar @local_expression-2; $o=$o+2) {
      my $r = 0;
      if ($local_expression[$o] eq '*') { $r = $local_expression[$o-1] * $local_expression[$o+1]; }
      elsif ($local_expression[$o] eq '+') { $r = $local_expression[$o-1] + $local_expression[$o+1]; }
      elsif ($local_expression[$o] eq '|') { $r = $local_expression[$o-1] . $local_expression[$o+1]; }
      else { die; }
      $local_expression[$o-1] = $r;
      splice @local_expression,$o,2;
      last;
    }
  }
  return $local_expression[0];
}

sub combinations {
    my ($symbols, $len) = @_;
    my @result = ();
    my $s_len = scalar @$symbols;
    for my $i (0..$s_len**$len - 1) {
        my $num = $i;
        my @combination;
        for my $position (1..$len) {
            unshift @combination, $symbols->[$num % $s_len];
            $num = int($num/$s_len);
        }
        push @result, \@combination;
    }
    return @result;
}