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 минут получается программа из одного предложения.