#!/usr/local/bin/tclsh foreach r [split [read stdin] \n] { if {[scan $r {%[^=] => %d %s} a b c] != 3} continue set qty($c) $b foreach i [split [string map {{ } {}} $a] ,] { scan $i {%d%s} j k lappend inputs($c) [list $j $k] set made($c) 0 } } if {[llength $argv] != 1} { puts stderr "usage: $argv0 ORE-per-FUEL" exit 1 } proc make {n chem} { global qty inputs made #puts "making: $n $chem" if {$chem eq "ORE"} { set made(ORE) [expr {$made(ORE) - $n}] if {$made(ORE) < 0} {return 0} #puts "$made(ORE) ORE left" return 1 } # Find the reaction we need to run, and then calculate how many times # to run it. if {$n == $qty($chem)} { set times 1 } else { set times [expr {($n + $qty($chem) - 1) / $qty($chem)}] } #puts "make $times batches of $chem" # Produce enough of each input chemical. # Consume them *as we go* so they don't get double-used. foreach i $inputs($chem) { lassign $i n2 chem2 if {$made($chem2) < ($times * $n2)} { if {! [make [expr {($times * $n2) - $made($chem2)}] $chem2]} { #puts "making [expr {$times*$n2}] $chem2 failed" return 0 } } else { #puts "already have $made($chem2) $chem2 (need [expr {$times*$n2}])" } incr made($chem2) [expr {-1 * $times * $n2}] #puts "consumed [expr {$times * $n2}] $chem2 ($made($chem2) left)" } # Inputs have been consumed, so create output. incr made($chem) [expr {$times * $qty($chem)}] #puts "created [expr {$times * $qty($chem)}] $chem" return 1 } set made(ORE) 1000000000000 set fuel [expr {1000000000000 / [lindex $argv 0]}] make $fuel FUEL puts "start with $fuel FUEL, $made(ORE) ORE left" while {$made(ORE) > 10000000 * [lindex $argv 0]} { make 1000000 FUEL incr fuel 1000000 puts ">> $fuel FUEL, $made(ORE) ORE left" } while {$made(ORE) > 10000 * [lindex $argv 0]} { make 1000 FUEL incr fuel 1000 puts ">> $fuel FUEL, $made(ORE) ORE left" } while {[make 1 FUEL]} { incr fuel } puts "made $fuel FUEL"