Компьютер — страшная сила!
Программистская банальность
Всё врут календари.
А. С. Грибоедов. Горе от ума
Пирамиды - большая загадка для всего человечества, нам, конечно, её не решить даже с помощью компьютера, но в мире есть и другие причудливые пирамиды, - например, числовые!
В довольно увесистой книге GehirnJogging под номером 147 можно найти вот такую задачу:
Условие таково: в основании пирамиды находятся все числа от 1 до 6, найти числа в пустых клетках, если каждое число, опирающееся на два нижних, равно их сумме.
Ясно, что в клетке над двойкой и пятёркой стоит число 2 + 5 = 7:
Что делать? - Либо думать, либо писать программу. Лень - двигатель прогресса, поэтому мы напишем программу, которая решит не только эту задачу, но и все подобные.
Интерфейс собираем, не мудрствуя лукаво, на один раз любой сгодится:
Результаты наших поисков выводим в список lstProtokol. Магическая кнопка sbtSolveнаходит все перестановки чисел 1, 2, 3, 4, 5, 6 в основании пирамиды, а также сумму, которая получается при этом в её вершине. Затем список сохраняем на диске, ублажив курсором кнопку sbtSaveProtokol.
Перестановки чисел будем искать грубой силой, без поиска изящных алгоритмов:
procedure TfrmMain.sbtSolveClick(Sender: TObject); |
|
var |
|
a1,a2,a3,a4,a5,a6,f: integer; |
|
s: string; |
|
begin |
|
lstProtokol.Items.clear; |
|
for a1:= 1 to 6 do begin |
|
for a2:= 1 to 6 do begin |
|
if a2=a1 then continue; |
|
for a3:= 1 to 6 do begin |
|
if (a3=a2) or (a3=a1) then continue; |
|
for a4:= 1 to 6 do begin |
|
if (a4=a3) or (a4=a2) or (a4=a1)then continue; |
|
for a5:= 1 to 6 do begin |
|
if (a5=a4) or (a5=a3) or (a5=a2) or (a5= |
|
nue; |
|
for a6:= 1 to 6 do begin |
|
if (a6=a5) or (a6=a4) or (a6=a3) |
|
(a6=a1)then continue; |
|
f:= a1 + a6 + 5*(a2+a5) + 10*(a3+a4); о . — f 1 • |
|
s:= ; if f < 100 then s:= s + '0'; |
|
s:= s+ inttostr(f)+' = '+ inttostr |
|
tostr(a2)+' '+ inttostr(a3)+' '+ inttostr(a4)+' '+ |
|
'+ inttostr(a6); |
|
lstProtokol.Items.add(s); |
|
end; |
|
end; |
|
end; |
|
end; |
|
end; |
|
end; |
|
end; |
|
На деле это выглядит так. В основании стоят 6 чисел от единицы до шестёрки, причём числа не повторяются. Значит, выписываем 6 вложенных циклов forи в каждом проверяем это условие. Если параметр цикла равен уже вышедшему ранее числу, то проверяем следующее (вот и процедура continueпригодилась!). Как только мы нашли очередную расстановку (шесть разных чисел в основании), вычисляем по правилам задачи сумму в вершине пирамиды:
f:= a1 + a6 + 5*(a2+a5) + 10*(a3+a4);
Хотите верьте, хотите нет, но она именно такая (посчитайте сами!)
Осталось красиво записать найденный вариант расстановки чисел и сумму в окно протокола.
К сожалению, в этом списке очень неудобно отыскивать нужную нам сумму в вершине. Но мы не будем утруждать себя сортировкой вариантов по возрастанию суммы, а просто запишем список в текстовый файл protokol.TXT:
//ЗАПИСАТЬ ПРОТОКОЛ НА ДИСК
procedureTfrmMain.sbtSaveProtokolClick(Sender: TObject);
var
s,fn: string; i: integer; f: textfile; begin
//savedialog1.DefaultExt:='txt'; savedialog1.Filter:=’Solutions (*.txt)|*.TXT’; savedialog1.FilterIndex:=1;
s:=extractfilepath(application.exename)+'solutions'; savedialog1.InitialDir:= s;
savedialog1.Title:=’Save the solution to the disk’;
//имя файла:
savedialog1.filename:=’protokol temp.txt’;
if not savedialog1.Execute then exit;
//имя конечного файла: fn:= savedialog1.filename; assignfile(f,fn);
if FileExists(savedialog1.filename) then
append(f) //- добавить информацию в конец файла
else rewrite(f); //- перезаписать файл
//записать протокол:
for i:=0 to (lstProtokol.Items.Count - 1) do writeln (f,lstProtokol.Items.Strings);
Closefile(f);
Messagebeep(0) end;
А затем откроем его в текстовом редакторе MicrosoftWord, отсортируем его и получим список protokol.doc, в котором легко найти нужное нам число в вершине пирамиды:
095 = 4 2 1 5 3 6
095 = 4 2 5 1 3 6
095 = 4 3 1 5 2 6
095 = 4 3 5 1 2 6
095 = 6 2 1 5 3 4
095 = 6 2 5 1 3 4
095 = 6 3 1 5 2 4
Всего можно насчитать 8 расстановок шести чисел, которые дают сумму 95, но нас интересуют только те, в которых двойка и пятёрка стоят на втором и третьем местах. И что мы видим: годятся две расстановки:
095 = 4 2 5 1 3 6 095 = 6 2 5 1 3 4,
значит, и решений у задачи тоже два.
Смотрим в ответ - одно.
Не верьте толстым книгам!
В книге ещё много таких задач, но мы их решили все разом и даже подкузьмили незадачливого немецкого автора, который не удосужился поискать и второе решение
И не надейтесь, что я написал всю программу с нуля! Компонент со списком, кнопки, процедуру записи списка в файл я благополучно экспортировал (легально!) из других своих программ. Добавить пришлось только незамысловатую процедуру составления списка вариантов - по времени дольше объяснять, чем «соорудить» такую программу.