#!/usr/bin/env tclsh9.0 namespace import ::tcl::mathop::* proc prng {seed} { set seed [expr {(($seed << 6) ^ $seed) & 0xffffff}] set seed [expr {(($seed >> 5) ^ $seed) & 0xffffff}] expr {(($seed << 11) ^ $seed) & 0xffffff} } # For each buyer, start with their seed, generate the 2000 new secrets, # which gives <= 1997 sequences of 4 deltas. Keep track of the first # time each sequence is seen for each buyer. Keep track of each buyer's # price-score for each sequence. # When all buyers have been iterated, check the score for each sequence # that has been seen. set sequences [dict create] ;# indexed by d1,d2,d3,d4 proc grind {buyer seed} { global sequences set n 2000 set d1 0; set d2 0; set d3 0; set d4 0 set seen [dict create] ;# indexed by d1,d2,d3,d4 for this buyer only set prev [% $seed 10] for {set i 0} {$i < $n} {incr i} { set newseed [prng $seed] set new [% $newseed 10] set d1 $d2; set d2 $d3; set d3 $d4 set d4 [- $new $prev] if {$i >= 3} { set key "$d1,$d2,$d3,$d4" if {! [dict exists $seen $key]} { dict set seen $key $new dict lappend sequences $key $new } } # puts [format "%8d: %d (%d)" $newseed $new $d4] set seed $newseed set prev $new } return 0 } # Find which sequence gives the highest total score. # Tally me banana. proc tally {} { global sequences set max 0 dict for {key val} $sequences { set b 0 foreach score $val { incr b $score } if {$b > $max} { puts "$key => $b" set max $b } } puts $max } set secrets [split [read stdin] \n] set buyer 0 foreach secret $secrets { if {$secret eq ""} continue set n [grind $buyer $secret] incr total $n incr buyer } tally # puts "" # foreach key [lsort [dict keys $score]] { # puts "$key [dict get $score $key]" # } # 2161 too low