Отказоустойчивый Hello World (он же Интервью)


66

В конце вашего интервью Злой Интервьюер говорит вам: «Мы заставляем всех наших кандидатов пройти короткий тест на кодирование, чтобы увидеть, действительно ли они знают, о чем говорят. Не волнуйтесь, это легко. И если вы создадите рабочая программа, я сразу предложу тебе работу. Он жестом просит вас сесть за соседний компьютер. «Все, что вам нужно сделать, - это создать работающую программу Hello World. Но», - и он широко улыбается, - «это ловушка. К сожалению, единственный компилятор, который у нас есть на этой машине, имеет небольшую ошибку. Он случайным образом удаляет один символ из файл исходного кода перед компиляцией. Хорошо, увидимся через пять минут! " И он выходит из комнаты, счастливо насвистывая.

Можете ли вы гарантировать, что вы получите работу?

Задание

Напишите программу, которая будет печатать Hello, world!на стандартный вывод даже после удаления одного символа из любой позиции в файле. Или подойди к этому как можно ближе.

Правила

Отсутствие постороннего вывода - Hello, world!должно быть единственной существенной вещью, выводимой на стандартный вывод. Можно включать другие символы, если они естественным образом производятся на выбранном вами языке - например, завершающий символ новой строки или что-то вроде этого [1] "Hello, world!"(например, если вы использовали R), но каждый раз он должен печатать одно и то же. Например, он не может печатать Hello, world!Hello, world!или Hello world!" && x==1иногда. Предупреждения, однако, разрешены.

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

Оценка Ваша оценка - это количество неудачных попыток вашей программы . Другими словами, количество отдельных позиций в вашем файле, где удаление символа не позволяет вашей программе работать. Самый низкий балл побеждает. В случае ничьей выигрывает самый короткий код.

Тривиальные решения, такие как "Hello, world!"на нескольких языках (оценка 15), являются приемлемыми, но они не выиграют. По крайней мере, я нашел решение Perl со счетом 4, которое я опубликую в конце концов.

Обновление: Официальный победитель будет использовать язык программирования, полный Тьюринга, и не будет использовать какой-либо предопределенный механизм печати Hello, world!. Любой используемый внешний ресурс (кроме стандартных библиотек для вашего языка) считается частью вашей программы и подлежит удалению одним и тем же символом. Эти требования были прикреплены к столу на заметке. Извиняюсь, если вы не видели их сначала.

Обновление 2: Да, ваша программа должна фактически выполнить задачу, описанную выше, чтобы получить оценку! Это означает, что он должен успешно напечатать Hello, world!хотя бы один раз. Это должно было быть очевидно. Переключатели командной строки и другие параметры, которые добавляют функциональность, также считаются частью вашей программы и подлежат удалению одним символом. Программа должна выполнить свою задачу без участия пользователя. Ошибка при компиляции учитывается в вашем счетчике ошибок.

Приятного программирования, и пусть вы получите работу. Но если вы потерпите неудачу, вы, вероятно, не захотите работать на этого злого босса.

Perl тестовый скрипт:

use warnings;
use strict;

my $program   = 'test.pl';
my $temp_file = 'corrupt.pl';
my $command = "perl -X $temp_file"; #Disabled warnings for cleaner output.
my $expected_result = "Hello, world!";

open my $in,'<',$program or die $!;
local $/;           #Undef the line separator   
my $code = <$in>;   #Read the entire file in.

my $fails = 0;
for my $omit_pos (0..length($code)-1)
{
    my $corrupt = $code;
    $corrupt =~ s/^.{$omit_pos}\K.//s;  #Delete a single character

    open my $out,'>',$temp_file or die $!;
    print {$out} $corrupt;  #Write the corrupt program to a file
    close $out;

    my $result = `$command`;    #Execute system command.
    if ($result ne $expected_result)
    { 
        $fails++;
        print "Failure $fails:\nResult: ($result)\n$corrupt";
    }
}

print "\n$fails failed out of " . length $code;

1
Может ли удаленный символ привести к тому, что программа не компилируется? Это все еще считается не работающим?
lochok

@lochok, да, это будет считаться провалом. Любой удаленный символ, который приводит к тому, что он Hello, World!не печатается, является ошибкой.

2
Аналогичный вопрос: codegolf.stackexchange.com/questions/4486/…
mowwwalker

@ Walkerneo, спасибо! Я искал похожие вопросы и не нашел этого. Я думаю, что это значительно отличается, хотя. В частности, этот вопрос гарантирует, что должны обрабатываться только модификации, приводящие к синтаксически корректному коду.

Не могли бы вы привести пример «параметров командной строки и других параметров, которые добавляют функциональность»? Вы имеете в виду переключатели и настройки, данные самой программе, или использование переключателей и настроек в среде сборки?
CasaDeRobison

Ответы:


129

Befunge, счет 0

Я думаю, что взломал это - никакое удаление одного символа не изменит выход.
Удаление любого символа из строки 1 ничего не меняет - оно все равно исчезает в том же месте.
Линии 2 и 3 являются избыточными. Обычно строка 2 выполняется, но если вы удаляете из нее символ, <пропускается, а строка 3 берет на себя ответственность.
Удаление новых строк тоже не сломало (это сломало мою предыдущую версию).
Нет тестовой программы, извините.

РЕДАКТИРОВАТЬ : очень упростил.

                              vv
@,,,,,,,,,,,,,"Hello, world!"<<
@,,,,,,,,,,,,,"Hello, world!"<<

Краткое объяснение потока:

  1. Befunge начинает исполняться сверху слева, двигаясь вправо. Пробелы ничего не делают.
  2. v поворачивает поток выполнения вниз, так что он идет вниз на одну строку.
  3. < поворачивает поток выполнения влево, поэтому он читает строку 2 в обратном порядке.
  4. "Hello, world!"толкает строку в стек. Это происходит в обратном порядке, потому что мы выполняем справа налево.
  5. ,выскакивает персонаж и печатает его. Последний нажатый символ печатается первым, что переворачивает строку еще раз.
  6. @ завершает программу

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

4
Так легко проверить и не участвовать в обсуждении. Genius!
Карма Fusebox

Поздравляю с отличным решением.

2
Я знаю, что это не код-гольф , но вот версия в 66 байтов .
MD XF

42

Perl, оценка 0

(147 символов)

Вот мое решение, которое мне удалось получить от 4 до 0:

eval +qq(;\$_="Hello, world!";;*a=print()if length==13or!m/./#)||
+eval +qq(;\$_="Hello, world!";;print()if*a!~/1/||!m/./#)##)||
print"Hello, world!"

Это должно появиться все на одной строке, чтобы работать; разрывы строк предназначены только для «читабельности».

Это использует патологически допустимый синтаксис Perl. Некоторые основные моменты:

  • Голые слова, которые не распознаются, рассматриваются как строки. Так что когда evalстановится evl, это не ошибка, если в этой точке допустима строка.
  • Унарный +оператор, который не делает ничего, кроме устранения неоднозначности синтаксиса в определенных ситуациях. Это полезно с вышеупомянутым, потому что function +argument(где + унарный) становится string + argument(дополнение), когда имя функции искажается и становится строкой.
  • Много способов объявить строки: строка в двойных кавычках qq( )может стать строкой в одинарных кавычках q(); строка, ограниченная скобками, qq(; ... )может стать строкой, разделенной точкой с запятой qq; ... ;. #внутренние строки могут устранить проблемы с балансировкой, преобразовав вещи в комментарии.

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


13
+1 для разрывов строк только для удобства чтения ...
Бакуриу

40

HQ9 +

Это никогда не приведет к желаемому результату, когда персонаж будет удален, поэтому он получит ноль очков.

HH

Когда я начну?


1
Это производит "привет, мир", а не "Привет, мир!" как указано.
Пол Р

16
Ерунда, язык был просто неверно указан в esolang wiki;)
skeevey

11
Хорошо, если на компьютере для собеседования установлен компилятор HQ9 + ... :)

Вы можете написать свой собственный глючный компилятор.
PyRulez

2
@ mbomb007 Этот интерпретатор печатает Hello, world!для Hкоманды.
Деннис

12

Befunge-98 , оценка 0, 45 байт

20020xx""!!ddllrrooww  ,,oolllleeHH""cckk,,@@

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

Несмотря на то, что оптимальное решение уже найдено (и здесь нет разрыва связи), я решил показать, что это можно значительно упростить с Befunge 98.

объяснение

20020xxНадежно устанавливает дельту (ступеньки указателя команды между клещами) , чтобы (2,0)таким образом , что , начиная с первым x, только каждой второй командой выполняется. Посмотрите этот ответ для подробного объяснения того, почему это работает. После этого код просто:

"!dlrow ,olleH"ck,@

Сначала мы помещаем все соответствующие коды символов в стек с помощью "!dlrow ,olleH". Затем ck,означает печать вершины стека ( ,), 13 ( cплюс 1) раз ( k). @завершает программу


11

J, 7 баллов

Выбор каждой буквы с нечетной позицией:

   _2{.\'HHeellllo,,  wwoorrlldd!!'
Hello, world!

5
То же самое в golfscript бы 4 балла:'HHeelllloo,, wwoorrlldd!!'2%
cardboard_box

@cardboard_box Не стесняйтесь представить его. :)
randomra

Проголосую, потому что я это понимаю, и это не похоже на обман.
Майкл Стерн

3

Befunge-93, оценка 0 (63 байта)

Я знаю, что это не проблема кода-гольфа, но я подумал, что было бы интересно посмотреть, можно ли улучшить существующее решение Befunge-93 с точки зрения размера. Первоначально я разработал эту технику для использования в аналогичной задаче с ошибкой 404 , но в этом случае необходимость в переносимой полезной нагрузке сделала решение с тремя строками более оптимальным.

Это не так хорошо, как ответ Мартина Befunge-98, но это все же довольно значительное сокращение выигрышного решения Befunge-93.

<>>  "!dlrow ,olleH">:#,_@  vv
  ^^@_,#!>#:<"Hello, world!"<<>#

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

объяснение

Есть две версии полезной нагрузки. Для неизмененной программы, первая <заставляет программу выполняться справа налево, оборачиваясь до конца строки, пока не достигнет vнаправления вниз ко второй строке и <направления слева направо в версию слева направо. полезной нагрузки.

Ошибка во второй строке приводит к тому, что финал <смещается влево и заменяется >направлением потока вправо. Команде #(bridge) нечего перепрыгивать, поэтому код просто продолжается до тех пор, пока не обернется и не достигнет a ^в начале строки, направив его до первой строки, а затем >направив прямо в право оставленный полезный груз.

Большинство ошибок в первой строке просто приводят к тому, что последние vкоманды сдвигаются на одну, но это не меняет основной поток кода. Однако удаление первого <немного отличается - в этом случае путь выполнения просто перенаправляется непосредственно в полезную нагрузку слева направо в первой строке.

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

В случае каких-либо сомнений я также протестировал скрипт perl, и он подтвердил, что «0 не удалось из 63».


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.