/* Zoo, buses and kids problem in Picat. https://dmcommunity.org/challenge/challenge-july-2018/ """ 300 kids need to travel to the London zoo. The school may rent 40 seats and 30 seats buses for 500 and 400 £. How many buses of each to minimize cost? """ This Picat model was created by Hakan Kjellerstrand, hakank@gmail.com See also my Picat page: http://www.hakank.org/picat/ */ import cp. main => go. /* CP model z = 3800 buses = [2,6] hyperfine: Time (mean ± σ): 36.9 ms ± 5.3 ms [User: 19.1 ms, System: 17.0 ms] Range (min … max): 22.3 ms … 45.3 ms 64 runs */ go => NumKids = 300, Seats = [30,40], Price = [400,500], N = Seats.len, % decision variables Buses = new_list(2), Buses :: 0..100, sum([Seats[I]*Buses[I] : I in 1..N]) #>= NumKids, Z #= sum([Buses[I]*Price[I] : I in 1..2]), solve($[min(Z)], Buses), println(z=Z), println(buses=Buses), nl. /* As a one-liner [[2,6],3800] Time (mean ± σ): 34.9 ms ± 5.5 ms [User: 18.3 ms, System: 16.6 ms] Range (min … max): 19.8 ms … 45.6 ms 59 runs */ go2 => K=300,S=[30,40],P=[400,500],N=S.len, B=new_list(2),B::0..100,sum([S[I]*B[I]:I in 1..N])#>=K, Z#=sum([B[I]*P[I]:I in 1..2]),solve($[min(Z)],B),println([B,Z]). /* Logic programming with minof/2 [s30 = 2,s40 = 6,z = 3800] Hyperfine: Time (mean ± σ): 35.9 ms ± 5.5 ms [User: 17.6 ms, System: 18.0 ms] Range (min … max): 15.0 ms … 43.2 ms 66 runs */ go3 => NumKids=300, member(Seat30,1..NumKids div 30), member(Seat40,1..NumKids div 40), Seat30*30 + Seat40*40 == 300, minof(zoo3(Seat30,Seat40,Z),Z), println([s30=Seat30,s40=Seat40,z=Z]), nl. zoo3(S30,S40,Z) => Z = S30*400 + S40*500. /* Imperative [[3800,2,6],[3900,6,3]] [seat30 = 2,seat40 = 6,z = 3800] Hyperfine: Time (mean ± σ): 35.4 ms ± 6.3 ms [User: 18.5 ms, System: 16.8 ms] Range (min … max): 18.9 ms … 45.7 ms 70 runs */ go4 => NumKids=300, Zs = [], foreach(Seat30 in 1..NumKids div 30) foreach(Seat40 in 1..NumKids div 40) if Seat30*30 + Seat40*40 == NumKids then Zs := Zs ++ [[Seat30*400+Seat40*500,Seat30,Seat40]] end end end, println(Zs.sort), [Z,Seat30, Seat40] = Zs.sort.first, println([seat30=Seat30,seat40=Seat40,z=Z]), nl.