geese.htm
Детская задачка.
Летит стая гусей, а навстречу ей - один гусь. Один гусь и говорит "Здравствуйте, сто гусей !". На что вожак отвечает :
- нас не 100 гусей. Вот если взять всех нас, до еще столько, да еще пол-столько, да еще четверть столько, до еще тебя гуся, то получится ровно сто гусей.
Спрашивается, сколько гусей в стае ?
Будем решать эту задачу при помощи суперкомпилятора. Пишем программу, которая по количеству гусей, определяет, подходит ли это количество под вопрос.
*$MST_FROM_ENTRY; $ENTRY Go { e.1 = <Eq (<A e.1>) (<G100 >)>; } A { 'gggg' e.1 = 'gggg' 'gggg' 'gg' 'g' <A e.1>; = 'g' ; } Eq { ( ) ( ) = T; ('g' e.1) ('g' e.2) = <Eq (e.1) (e.2)>; (e.1) (e.2) = F; } G100 { = 'gggggggggggggggggggggggggggggggggggggggggggggggggg' 'gggggggggggggggggggggggggggggggggggggggggggggggggg' ; } |
Комментарии, ввиду простоты программы, излишни. Суперкомпилируем эту программу и получаем
* InputFormat: <Go e.41 > $ENTRY Go { 'gggggggggggggggggggggggggggggggggggggggg' e.41 = F ; 'gggggggggggggggggggggggggggggggggggg' = T ; 'gggggggggggggggggggggggggggggggg' = F ; 'gggggggggggggggggggggggggggg' = F ; 'gggggggggggggggggggggggg' = F ; 'gggggggggggggggggggg' = F ; 'gggggggggggggggg' = F ; 'gggggggggggg' = F ; 'gggggggg' = F ; 'gggg' = F ; = F ; } |
Если 36 гусей, то истина, иначе - ложь. Представляет интерес первое предложение - мы не только нашли ответ, но и доказали, что других решений нет.
Теперь убираем в функции Eq третье предложение, получаем
$ENTRY Go { 'gggggggggggggggggggggggggggggggggggg' = T ; } |
Пробуем изменить 100 гусей на 101 гуся, получаем
$ENTRY Go { 'gggggggggggggggggggggggggggggggggggggggg' e.41 = F ; 'gggggggggggggggggggggggggggggggggggg' = F ; 'gggggggggggggggggggggggggggggggg' = F ; 'gggggggggggggggggggggggggggg' = F ; 'gggggggggggggggggggggggg' = F ; 'gggggggggggggggggggg' = F ; 'gggggggggggggggg' = F ; 'gggggggggggg' = F ; 'gggggggg' = F ; 'gggg' = F ; = F ; } |
Интересно, что если в первой задаче в функции A поменять порядок предложений, то есть одного гуся рассматривать сначала, то в результирующей программе меняется порядок предложений на обратный -
$ENTRY Go { = F ; 'gggg' = F ; 'gggggggg' = F ; 'gggggggggggg' = F ; 'gggggggggggggggg' = F ; 'gggggggggggggggggggg' = F ; 'gggggggggggggggggggggggg' = F ; 'gggggggggggggggggggggggggggg' = F ; 'gggggggggggggggggggggggggggggggg' = F ; 'gggggggggggggggggggggggggggggggggggg' = T ; 'gggggggggggggggggggggggggggggggggggggggg' e.41 = F ; } |
Предложенный алгоритм не совсем соответствует условию задачи (мы немного подсказываем суперкомпилятору). Поэтому попробуем более адекватный способ
*$MST_FROM_ENTRY; $ENTRY Go { e.1 = <Eq (<A e.1>) (<G100 >)>; } A { e.1 = <G e.1> <G e.1> <G12 e.1> <G14 e.1> 'g'; } G { e.1 = e.1; } G12 { = ; 'gg' e.1 = 'g' <G12 e.1>; } G14 { = ; 'gggg' e.1 = 'g' <G14 e.1>; } Eq { ( ) ( ) = T; ('g' e.1) ('g' e.2) = <Eq (e.1) (e.2)>; (e.1) (e.2) = F; } G100 { = 'gggggggggggggggggggggggggggggggggggggggggggggggggg' 'gggggggggggggggggggggggggggggggggggggggggggggggggg' ; } |
Суперкомпилятор работал 11 минут, но справился с этой задачей. В результирующей программе сто предложений, поэтому ее не приводим. Если же в функции Eq убрать ложь, то опять за 11 минут получается программа из одного предложения.