% % A program to solve the logic puzzle from % https://www.ahapuzzles.com/logic/logic-puzzles/a-new-personal-computer/ % (Aha!Puzzles by james@ahapuzzles.com) % % Author: Joachim Schimpf, 2024 % Creative Commons Attribution 4.0 International License. % % ?- go. % 15.0' 2.3MHz 250GB 699Euro % 13.0' 2.0MHz 320GB 999Euro % 21.5' 2.7MHz 1024GB 1149Euro % 15.6' 2.5MHz 500GB 1349Euro <---Andrew's Computer % 27.0' 3.1MHz 750GB 1649Euro % Yes (0.01s cpu, solution 1, maybe more) % No (0.01s cpu) % :- lib(ic). :- import ordered/2 from ic_global. go :- N = 5, length(Disks, N), length(Prices, N), length(Processors, N), length(Screens, N), Disks #:: [250,320,500,750,1024], Prices #:: [699,999,1149,1349,1649], Processors #:: [20,23,25,27,31], % scaled by 10 Screens #:: [130,150,156,215,270], % scaled by 10 alldifferent(Disks), alldifferent(Prices), alldifferent(Processors), alldifferent(Screens), % 1. Andrew bought the computer which was three hundred % Euros less than the PC which has a processor that is 0.4 MHz % more powerful than the one which has a 21.5' screen. element(AndrewComputer, Prices, AndrewPrice), same_pos([Prices:HigherPrice, Processors:FasterProcessor]), same_pos([Screens:215, Processors:Screen215Processor]), AndrewPrice #= HigherPrice-300, FasterProcessor #= Screen215Processor+4, % 2. The five computers are: the one chosen by Andrew (which % doesn't have the 27' screen), the one which has the 2.0-MHz % processor, the computer that has a 250 GB HD, the one which % has a price of 1,149 Euros and the computer (which doesn't % have the 15' screen) that has the HD bigger than the one % chosen by Andrew but smaller than that the one which has % the 2.7 MHz processor. alldifferent([AndrewComputer,Processor20Computer, Disk250Computer,Euro1149Computer,OtherComputer]), element(AndrewComputer, Screens, AndrewScreen), AndrewScreen #\= 270, element(Processor20Computer, Processors, 20), element(Disk250Computer, Disks, 250), element(Euro1149Computer, Prices, 1149), element(OtherComputer, Screens, OtherScreen), OtherScreen #\= 150, element(OtherComputer, Disks, OtherDisk), element(AndrewComputer, Disks, AndrewDisk), element(Processor27Computer, Processors, 27), element(Processor27Computer, Disks, Processor27Disk), AndrewDisk #< OtherDisk, OtherDisk #< Processor27Disk, % 3. The computer with the 320 Gb HD has either the 2.0 or the % 2.3 MHz processor.The processor of the computer which has % the 15' screen is more powerful than the one in the computer % that costs 999 euros but less powerful than the processor that % is included in the 1,349 Euros computer. same_pos([Disks:320, Processors:Disk320Processor]), Disk320Processor #:: [20,23], same_pos([Screens:150, Processors:Screen150Processor]), same_pos([Prices:999, Processors:Euro999Processor]), same_pos([Prices:1349, Processors:Euro1349Processor]), Euro999Processor #< Screen150Processor, Screen150Processor #< Euro1349Processor, % 4. The computer that has the 27' screen doesn't have the 320 % Gb hard drive. The 500 GB HD is included in the computer % that has a more powerful processor and a larger size screen % than the one which costs 699 euros (which doesn't include % the 320 Gb HD). same_pos([Screens:270, Disks:Screen270Disk]), Screen270Disk #\= 320, same_pos([Disks:500, Processors:Disk500Processor, Screens:Disk500Screen]), same_pos([Prices:699, Processors:Euro699Processor, Screens:Euro699Screen, Disks:Euro699Disk]), Disk500Processor #> Euro699Processor, Disk500Screen #> Euro699Screen, Euro699Disk #\= 320, % Exclude symmetric solutions by ordering some property, e.g. price ordered(<, Prices), % Search for a solution labeling([Disks,Processors,Prices,Screens]), % Print result ( for(I,1,N), foreach(D,Disks), foreach(P,Processors), foreach(E,Prices), foreach(S,Screens), param(AndrewComputer) do S10 is S/10, P10 is P/10, printf("%.1f' %.1fMHz %4dGB %4dEuro", [S10,P10,D,E]), ( I == AndrewComputer -> writeln(" <---Andrew's Computer") ; nl ) ). % An auxiliary convenience predicate, with the meaning % same_pos([Vector_1:Value_1,...,Vector_n:Value_n]) iff % there is an Index such that Vector_i[Index] = Value_i for all i same_pos(VectorsValues) :- ( foreach(Vector:Value,VectorsValues), param(_I) do element(_I, Vector, Value) ).