Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/perl
- $filename = "16.txt";
- open(FILE, $filename);
- @data = <FILE>;
- close(FILE);
- %rules = ();
- $myticket = "";
- @tickets = ();
- @validtickets = ();
- %ruleorder = ();
- @ra = ();
- # Read the file into variables.
- foreach $line (@data) {
- $line =~ s/\n//sgi;
- $line =~ s/\r//sgi;
- $line =~ s/\t//sgi;
- # Rule description
- if ($line =~ m/^([a-z ]*): (\d+)-(\d+) or (\d+)-(\d+)$/) {
- $rules{$1} = $2."-".$3."-".$4."-".$5;
- }
- # A ticket line. If my ticket is not set, the line is first ticket line, thus its MY ticket.
- if ($line =~ m/^\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+,\d+$/) {
- if (length($myticket) < 20) {
- $myticket = $line;
- }
- else
- {
- push(@tickets, $line);
- }
- }
- }
- $scanerror = 0;
- # Loop through all OTHER tickets.
- foreach $ticket (@tickets) {
- @fields = split(",",$ticket);
- $vticket = 1;
- foreach $field (@fields) {
- # Loop through all fields in ticket.
- $valid = 0;
- foreach $rule (keys %rules) {
- # Check field against all rules.
- ($lowa, $higha, $lowb, $highb) = split("-", $rules{$rule});
- if (((int($field) >= $lowa)&&(int($field) <= $higha)) || ((int($field) >= $lowb)&&(int($field) <= $highb))) {
- $valid = 1;
- }
- }
- if ($valid == 0) {
- # If all rules are invalid, then the field is invalid, add it to scan error rate.
- $scanerror = $scanerror + int($field);
- $vticket = 0;
- }
- }
- if ($vticket == 1) {
- # Ticket is valid - theres no invalid fields in ticket. Add it to valid ticket tally for part 2.
- push(@validtickets, $ticket);
- }
- }
- print "P1: $scanerror \n";
- $totalrulecount = 0;
- # This is like soduku - multiple rules are valid for fields, but in such a way that if you "spend" the rules in the right order, there will only be one rule that is valid excluding the spent fields.
- while ($totalrulecount < 20) { # If we found the order for all rules, we are done.
- @rulecount = ();
- for ($i = 0; $i < 20; $i++) { # Loop through all fields
- $foundrule = "";
- foreach $rulename (keys %rules) {
- if ($ruleorder{$rulename} > 0) {
- next; # Rule is spent - skip it.
- }
- $validrule = 0;
- ($lowa, $higha, $lowb, $highb) = split("-", $rules{$rulename});
- foreach $validticket (@validtickets) {
- @fields = split(",",$validticket);
- if (((int($fields[$i]) >= $lowa)&&(int($fields[$i]) <= $higha)) || ((int($fields[$i]) >= $lowb)&&(int($fields[$i]) <= $highb))) {
- $validrule++;
- }
- }
- if ($validrule == ($#validtickets + 1)) { # If rule is valid for all tickets, we add it to rulecount.
- $rulecount[$i]++;
- $foundrule = $rulename;
- }
- }
- if ($rulecount[$i] == 1) { # If there is only one rule that is valid for all tickets, not two or more, add it to ruleorder.
- $ruleorder{$foundrule} = $i + 1;
- $totalrulecount++;
- }
- }
- }
- # Add the fields to @ra - in the order as specified by the %ruleorder hash array.
- for ($i = 1; $i < 21; $i++) {
- foreach $r (keys %ruleorder) {
- if ($ruleorder{$r} == $i) {
- push(@ra, $r);
- }
- }
- }
- @myticketfields = split(",",$myticket);
- $totalsum = 1;
- # Multiple all departure fields
- for ($i = 0; $i < 20; $i++) {
- if ($ra[$i] =~ m/^departure/) {
- $totalsum = $totalsum * int($myticketfields[$i]);
- }
- }
- print "P2: $totalsum \n";
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement