Луковое программирование

22

Используя только пригодный для печати ASCII (шестнадцатеричные коды от 20 до 7E), напишите квадратную базовую программу N × N без комментариев, которая окружена еще 4 слоями , создав квадратную программу (N + 8) × (N + 8) (N> 0) , Для N = 3 макет (который будет заменен реальным кодом) выглядит следующим образом:

44444444444
43333333334
43222222234
43211111234
4321CCC1234
4321CCC1234
4321CCC1234
43211111234
43222222234
43333333334
44444444444
  • C представляют основную программу 3 × 3.
  • 1 представляют первый слой, 2 представляют второй слой и т. Д.

Программа всегда принимает строку целых чисел, разделенных пробелом, например, 0 -1 31 -1 2 2 2через stdin или аналогичные (это должны быть просто числа, без кавычек, скобок или чего-либо еще). Вывод зависит от того, какие части макета были запущены.

Существует пять способов запуска программы (новые строки включены в прогон). Каждый делает что-то свое в списке:

  1. Запустите только ядро:

    CCC
    CCC
    CCC
    

    Это вычисляет максимум абсолютных значений элементов входного списка и печатает COREна новой строке много раз. Если максимальное значение равно 0, ничего не выводится (новая строка в порядке).

    • Выход для 0 -1 31 -1 2 2 2будет

      CORE
      CORE
      ...
      

      31 раз

  2. Запустите ядро ​​со слоем 1:

    11111
    1CCC1
    1CCC1
    1CCC1
    11111
    

    Это выводит среднее ( среднее арифметическое ) значений списка в стандартную точность с плавающей запятой.

    • Выход для 0 -1 31 -1 2 2 235/7 = 5( 5.0в порядке).
  3. Запустите ядро ​​со слоями 1 и 2:

    2222222
    2111112
    21CCC12
    21CCC12
    21CCC12
    2111112
    2222222
    

    Это выводит разделенный пробелами список перевернутого списка ввода.

    • Выход для 0 -1 31 -1 2 2 2будет 2 2 2 -1 31 -1 0.
  4. Запустите ядро ​​со слоями 1, 2 и 3 (рисунок должен быть очевидным).
    Это выводит разделенный пробелами список отсортированного списка ввода.

    • Выход для 0 -1 31 -1 2 2 2будет -1 -1 0 2 2 2 31.
  5. Запустите ядро ​​со слоями 1, 2, 3 и 4.
    Это выведет разделенный пробелами список входного списка с удаленными дубликатами, порядок не имеет значения.

    • Выход для 0 -1 31 -1 2 2 2может быть -1 0 2 31.

Весь вывод - это стандартный вывод или аналогичная альтернатива.

Только эти 5 комбинаций макетов имеют указанное поведение.

Заметки

  • Комментарии не допускаются в ядре или слоях или их комбинациях. Код, который не работает или не делает ничего конструктивного, не считается комментарием.
  • Помните, что ядро ​​может иметь любые (положительные) размеры N × N, но слои имеют толщину всего один символ.
  • Вы можете предположить, что у ввода нет начальных или конечных пробелов и ровно один пробел между числами. Он всегда будет содержать хотя бы одно число. (Списки вывода тоже должны быть отформатированы.)
  • Вы можете предположить, что список и вычисления, необходимые для вывода, не будут иметь значений, которые переполняют (или уменьшают) ваши целые числа (если их максимум равен чему-то разумному, например, 2 16 ).

счет

Написание этой программы обычно было бы легко. Писать его с небольшим ядром сложно.

Программа с наименьшим размером ядра (наименьшим N) побеждает. В случае связей победителем является полная программа (квадрат (N + 8) × (N + 8)) с наименьшим количеством различных символов (не считая перевода строки).

Пожалуйста, укажите ваше значение N в верхней части вашего ответа.

Кальвин Хобби
источник
1
Я думал, что это будет еще один из тех новых типов
Оптимизатор
Могу ли я использовать язык, который игнорирует все после новой строки?
Исаак
1
@isaacg Да (до тех пор, пока символ новой строки не считается символом комментария, что было бы странно).
Увлечения Кэлвина
3
@Optimizer Не искушай меня ... " Каждый ответ добавляет новый слой к луковому коду, чтобы он делал что-то новое со списком ... "
Увлечения Кэлвина
1
@ Оптимизатор Нет. (Я знаю, что эти правила ввода-вывода довольно суровы, но для обеспечения согласованности между языками.)
Увлечения Кэлвина

Ответы:

10

CJam, N = 5, 27 (26) уникальных персонажей

Это 26 символов, если я не считаю пробелы. На самом деле программа может быть преобразована в ту, которая не использует пробелы, просто заполняя все пустые пробелы no-ops (например, _;который дублирует верхний элемент стека и затем отбрасывает, или сортируя массив снова и снова), но это будет просто отвлекать от фактического кода.

l~]_|S*      
{l~]$S*      
 {l~]W%S*    
  {l~]_,\    
   {l~]{z    
    }%$W=    
    "CORE    
    "*       
         }   
   ;:+d\/ }  
  ;        } 
 ;          }
;            

Проверьте это здесь.

Ядро

l~]{z
}%$W=
"CORE
"*

(Плюс пустая строка.)

Я уверен, что N = 4 это не может быть сделано в CJam (и я уверен, что Деннис убедит меня в обратном: D). Выше указано 17 символов, и, хотя может быть возможно уменьшить его до 16 (например, если у CJam не было ошибки, которую можно было бы задушить :z, что требует {z}%или с помощью ARGV), я не думаю, что вы можете подойти в макете без введения разрыва строки внутри CORE.

Все реализации очень простые решения поставленных задач. Все они начинаются с того, l~]что читает STDIN, оценивает его и помещает в массив.

Предыдущий слой всегда окружен {...} , что делает его блоком, который не выполняется автоматически. И вместо того, чтобы выполнить его, я просто отбрасываю его из стека ;, поэтому ни один уровень не зависит от кода предыдущего уровня. На уровне 1 код не помещался в первую строку, поэтому я продолжил его, отбросив основной блок.

Теперь для актуальных программ:

  • Core:

    {z}%$W="CORE
    "*
    

    Карта absна список, отсортировать его, взять последний элемент, повторитьCORE (и разрыв строки) столько раз.

  • Слой 1:

    _,\:+d\/
    

    Дублируйте список, возьмите длину, поменяйте местами элементы стека, получите сумму, приведите к double , поменяйте местами элементы стека, разделите. Я думаю, что это может быть короче, но нет никаких стимулов для этого.

  • Слой 2:

    W%S*
    

    Обратный массив, риффл с пробелами.

  • Слой 3:

    $S*
    

    Сортируй массив, раздувай с пробелами.

  • Слой 4:

    Дублируйте, возьмите набор, соедините пробелы.

Также возможны некоторые другие оптимизации, такие как повторное использование ;и *Sуровня 2, но, опять же, но это не влияет на оценку.

Мартин Эндер
источник
17

Python 2 - N = 17, 53 символа

О, я люблю проблемы с компоновкой исходного кода с помощью Python ...

i=4                     ;
ii=3                    ;
iii=2                   ;
iiii=1                  ;
iiiii=0;R=raw_input     ;
iiiii;w=R().split()     ;
iiiii;n=map(int,w)      ;
iiiii;S=set(n);M=max    ;
iiiii;s=sorted(n)       ;
iiiii;J="\n".join       ;
iiiii;j=" ".join        ;
iiiii;k=M(map(abs,n))   ;
iiiii;A=J(["CORE"]*k)   ;
iiiii;B=sum(n)/len(n)   ;
iiiii;C=j(w[::-1])      ;
iiiii;D=j(map(str,s))   ;
iiiii;E=j(map(str,S))   ;
iiiii;P=A,B,C,D,E       ;
iiiii;print P[i]        ;
iiiii;" /__----__\  "   ;
iiiii;"|/ (')(') \| "   ;
iiii;"  \   __   /  "   ;
iii;"   ,'--__--'.   "  ;
ii;"   /    :|    \   " ;
i;"   (_)   :|   (_)   ";

Тем не менее, есть еще неиспользованные пробелы.

Я все еще мог бы улучшить количество уникальных символов, но я буду придерживаться лучшей читабельности - если она вообще будет.

Редактировать: О, это снова Стэн !

Фалько
источник
Вы, вероятно, можете сохранить некоторые строки, используя псевдоним вместо i=*трюка
M.Herzkamp,
@ M.Herzkamp: алиасинг printневозможен в Python 2. Но, конечно, возможно, есть место для улучшения - возможно, с использованием Python 3.
Falko
Я не знаю Python, но не пропущено ли это абсолютное значение в выводе кода ядра -c*max(n)
nutki
@nutki: Ты прав! Я не читал внимательно. Но я смог это исправить.
Фалько
6

Python 3: N = 11, 40 различных символов

if 1:              
 if 1:             
  if 1:            
   if 1:           
    p=print;R=0    
    a=input()      
    b=a.split()    
    m=map;a=abs    
    E=max;l=len    
    n=m(int,b);    
    C=['CORE']     
   "R=E(m(a,n))"   
   OO=C*R;s=sum    
   "x='\n'.join"   
   "p(x(O))    "   
  "p(s(n)/l(b)) "  
 "p(*b[::-1])    " 
"p(*sorted(n))    "
p(*set(n))         

Спасибо @Falko за то, что ты моя муза. Это работает, потому что Python не создает новую область видимости для каждого оператора if, поэтому переменные сохраняются во внешних printоператорах. Раздражает то, что mapобъект (в нашем случае n) можно использовать только один раз. Так что нужно было зачеркнуть R=E(...)строку, но потомR не было определено. Поэтому мне повезло, что в первой строке осталось четыре пробела!

Вывод может быть решен путем предоставления нескольких элементов *b[::-1]вместо списка. Альтернатива ' '.join(...)была бы слишком длинной.

M.Herzkamp
источник
Прекрасный! Приятно видеть альтернативный подход к работе с переменными началами строк в python. Просто несколько коротких операторов if и все эти пробелы в порядке. :)
Фалько
@Falko: Недостатком является то, что нет места для Стэна :(
M.Herzkamp
2

C (gcc) , N = 15, 47 уникальных символов

Предполагает sizeof(int) == 4и sizeof(int*) >= sizeof(int).

;                     ;
 ;                   ; 
  ;                 ;  
   ;           float   
    s;c(a,b)int*a,*    
    b;{b=*b-*a;}i,n    
    ,*f;*q,*R,C,E ;    
    main(a){for(;0<    
    scanf("%i",&a);    
    i=i<abs(a)?a:i,    
    s+=f[n-!0]=a)f=    
    realloc(f,++n*4    
    );qsort(f,n*C,4    
    ,c);for(i=q?R?n    
    :!0:i;i--;a=f[i    
    ])!E|n-i<2|a!=f    
    [i]&&printf(q?R    
    ?R:q:"CORE\n",!    
    q+R?f[i]:s/n);}    
   ;*q="%f";       ;   
  ;*R="%.0f ";      ;  
 ;C=!0;              ; 
;E=!0;                ;

4 слоя

3 слоя

2 слоя

1 слой

ядро

gastropner
источник
0

Рунические чары , N = 9, N = 8, 38 символов

/ o/\  \     \S\
" //RiU\      \}
@            q "
"        }+1\r @
}   ^U \    {q "
     \{\?)}\+  }
  o\/'|A:{:/R' S
 //r/Ril2=?\?R :
   ,A~/"OC"/=? {
   @| \"RE"\3= =
 D$\' /rqka/l2S?
    i \*@   il\/
   'R1i     Ui ~
 R$/Rak      U \
 ?!D  Rlril1-{=
R   R: }S:{=?\~

Попробуйте онлайн!

Оказывается, я ошибался , я забыл, что у меня уже была явная oкоманда srt, потому что я столкнулся с проблемой «сортировки списка» раньше. Это, однако, ограничивает размер входных данных, которые может принимать конечная программа (8 значений) из-за внутренних затрат на команду sort. Небольшая настройка может увеличить размер ввода до 13 за счет одного уникального символа или до 19 для двух уникальных символов (все дополнительные символы находятся на уровне 1 и добавляются одновременно, но увеличение емкости стека IP не необходимо до уровня 3, так как C, L1 и L2 могут выполнять свои вычисления, не сохраняя весь ввод в память).

Core: попробуйте онлайн!

Уровень 1: Попробуйте онлайн!

Уровень 2: Попробуйте онлайн!

Уровень 3: Попробуйте онлайн!

Уровень 4: Попробуйте онлайн!

Дальнейшее сжатие маловероятно из-за меньшего пространства, требующего увеличения количества символов управления потоком. Я нашел схему, которая дала 9 пустых мест в основной программе, но этого недостаточно, как нам нужно (правильно расположенная) 15.

Объяснить, как работает любая из этих программ, сложно без визуальной карты пути, по которой идет IP, что является громоздким и трудоемким для построения. Начальной точкой входа является левый верхний угол программы Core ( ^), который обеспечивает согласованное управление потоком при добавлении новых слоев, так как каждый слой имеет возможность перехватывать новую добавленную линию вверху или внизу.

Слои 1 и 2 пересекаются внизу (так что верхняя линия остается пустой для будущих слоев), а затем выполняют свои операции вдоль правого края (петля, расположенная вертикально). Слой 1 немного слишком длинный и также принимает 3 символа вдоль верхнего края, но диагональный рефлектор ( \) в верхнем правом углу выравнивает IP со следующей итерацией цикла.

Слой 3 перехватывает вдоль верхнего края, чтобы захватить первое входное значение перед перенаправлением на нижний край (Слой 4 оставляет NOP в этом столбце в нижней строке) и считывает полный ввод, используя цикл нижнего края, перенаправляя вниз Команда ( D) в левом нижнем углу. Оттуда IP отскакивает несколько раз, прежде чем оказаться в $цикле output ( ) в нижнем левом углу для разделения значений в пространстве.

Уровень 4 использует все функциональные возможности уровня 3 (отсюда и пустое пространство), но перехватывает его собственный новый верхний край (верхний левый), чтобы выполнить свои собственные функции в конце обработки уровня 3. В верхний левый угол вставляется строка, "@"которая используется для обозначения конца массива перед входом в цикл обработки вдоль нижнего. Если найдено повторяющееся значение, оно выталкивается ( ~нижний правый угол), в противном случае берется ветвь, которая потребляет новый правый край. Эта боковая ветвь проверяет, достигнут ли конец массива, и, если это так, вырвется и отправится в тот же разделенный пробелами выходной цикл из уровня 3. В противном случае используйте пустое пространство на уровне 3, чтобы вернуться к главному петля.

Draco18s
источник