Bonjour tout le monde, tolérant aux pannes

66

À la fin de votre entretien, l’interviewer pour le mal vous dit: «Nous demandons à tous nos candidats de passer un bref test de codage pour savoir s’ils savent vraiment de quoi ils parlent. Ne vous inquiétez pas; c’est facile. Et si vous créez un programme de travail, je vais vous offrir le travail immédiatement. " Il vous fait signe de vous asseoir devant un ordinateur à proximité. "Tout ce que vous avez à faire est de créer un programme Hello World qui fonctionne. Mais" - et il sourit largement - "il ya un problème. Malheureusement, le seul compilateur que nous avons sur cette machine a un petit bogue. Il supprime de manière aléatoire un caractère du fichier de code source avant la compilation. Ok, on se voit dans cinq minutes! " Et il sort de la pièce en sifflant joyeusement.

Pouvez-vous garantir que vous obtiendrez le travail?

La tâche

Ecrivez un programme qui imprimera Hello, world!sur la sortie standard même après la suppression d'un seul caractère de n'importe quelle position du fichier. Ou venez aussi près que possible de cela.

Les règles

Pas de sortie étrangère - Hello, world!doit être la seule chose importante imprimée sur la sortie standard. Il est correct d’inclure d’autres caractères s’ils sont générés naturellement par la langue de votre choix, par exemple un fin de nouvelle ligne ou même quelque chose comme [1] "Hello, world!"(par exemple si vous utilisiez R), mais il doit imprimer exactement la même chose à chaque fois. Il ne peut pas imprimer Hello, world!Hello, world!ou Hello world!" && x==1de temps en temps, par exemple. Les avertissements sont toutefois autorisés.

Test Pour pouvoir déterminer votre score, vous devez tester chaque permutation possible du programme: testez-la à chaque caractère supprimé et vérifiez si le résultat obtenu est correct. J'ai inclus un programme Perl simple à cet effet ci-dessous, qui devrait fonctionner dans de nombreuses langues. Si cela ne fonctionne pas pour vous, veuillez créer un programme de test et l'inclure dans votre réponse.

Scoring Votre score est le nombre d'échecs de votre programme . En d'autres termes, le nombre de positions individuelles dans votre fichier où la suppression d'un caractère empêche votre programme de fonctionner. Le score le plus bas gagne. En cas d'égalité, le code le plus court l'emporte.

Des solutions triviales telles que "Hello, world!"plusieurs langues (score de 15) sont acceptables, mais elles ne vont pas gagner. J'ai au moins trouvé une solution Perl avec un score de 4, que je posterai éventuellement.

Mise à jour: le gagnant officiel utilisera un langage de programmation complet de Turing et n'utilisera aucun mécanisme prédéfini qui imprime Hello, world!. Toute ressource externe (autre que les bibliothèques standard de votre langue) utilisée est considérée comme faisant partie de votre programme et sujette à la même suppression d'un caractère. Ces exigences étaient collées au bureau sur un post-it. Toutes mes excuses si vous ne les avez pas vues au début.

Mise à jour 2: Oui, votre programme doit effectivement accomplir la tâche décrite ci-dessus afin de recevoir un score! Ce qui signifie qu'il devrait réussir à imprimer Hello, world!au moins une fois. Cela aurait dû être évident. Les commutateurs de ligne de commande et les autres paramètres qui ajoutent des fonctionnalités sont également pris en compte dans votre programme et sont sujets à la suppression d'un caractère. Le programme doit accomplir sa tâche sans aucune intervention de l'utilisateur. Un échec de la compilation compte dans votre nombre d'échecs.

Bonne programmation, et pouvez-vous obtenir le travail. Mais si vous échouez, vous ne voudriez probablement pas travailler pour ce méchant patron de toute façon.

Script de test 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;
dkudriavtsev
la source
1
Le caractère supprimé peut-il empêcher le programme de compiler? Est-ce toujours considéré comme ne fonctionnant pas?
lochok
@ Lochok, oui, cela compterait comme un échec. Tout caractère supprimé entraînant la Hello, World!non-impression est un échec.
2
Question similaire: codegolf.stackexchange.com/questions/4486/…
mowwwalker
@Walkerneo, merci! J'ai cherché des questions similaires et je n'ai pas trouvé celle-là. Je pense que cela est très différent, cependant. En particulier, cette question garantit que seules les modifications aboutissant à un code syntaxiquement valide doivent être traitées.
Pourriez-vous donner un exemple de "commutateurs de ligne de commande et autres paramètres qui ajoutent des fonctionnalités"? Voulez-vous dire des commutateurs et des paramètres donnés au programme lui-même, ou en utilisant des commutateurs et des paramètres dans l'environnement de construction?
CasaDeRobison

Réponses:

129

Befunge, Score 0

Je pense que je l'ai craqué - aucune suppression de caractère unique ne changera la sortie.
La suppression de tout caractère de la ligne 1 ne change rien - il reste au même endroit.
Les lignes 2 et 3 sont redondantes. Normalement, la ligne 2 est exécutée, mais si vous en supprimez un, la ligne <est manquée et la ligne 3 est prise en charge.
La suppression de nouvelles lignes ne casse pas non plus (cela a cassé ma version précédente).
Aucun programme de test, désolé.

EDIT : beaucoup simplifié.

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

Une brève explication du flux:

  1. Befunge commence à s'exécuter en haut à gauche et se déplace à droite. Les espaces ne font rien.
  2. v tourne le flux d'exécution vers le bas, donc il descend d'une ligne.
  3. < tourne le flux d'exécution vers la gauche, de sorte qu'il lit la ligne 2 dans l'ordre inverse.
  4. "Hello, world!"pousse la chaîne vers la pile. Il est poussé dans l'ordre inverse, car nous nous exécutons de droite à gauche.
  5. ,fait apparaître un caractère et l’imprime. Le dernier caractère poussé est imprimé en premier, ce qui inverse encore une fois la chaîne.
  6. @ termine le programme.
Ugoren
la source
2
+1, excellente solution. Je ne pense pas qu'un programme de test soit nécessaire, car il est évident qu'il n'y a qu'un petit nombre de suppressions potentiellement significatives.
4
Tellement facile à vérifier et aucune discussion impliquée. Génie!
Karma Fusebox
Félicitations pour une excellente solution.
2
Je sais que ce n'est pas du code-golf , mais voici une version en 66 octets .
MD XF
42

Perl, Score 0

(147 caractères)

Voici ma solution, que j'ai réussi à obtenir de 4 à 0:

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

Il doit apparaître sur une seule ligne pour fonctionner. les sauts de ligne servent uniquement à la "lisibilité".

Il bénéficie de la syntaxe permissive pathologiquement de Perl. Quelques faits saillants:

  • Les mots nus qui ne sont pas reconnus sont traités comme des chaînes. Ainsi, quand evaldevient evl, ce n'est pas une erreur si une chaîne est autorisée à ce stade.
  • +Opérateur unaire , qui ne fait rien d'autre que la syntaxe non ambiguë dans certaines situations. Ceci est utile avec ce qui précède, car function +argument(où + est unaire) devient string + argument(addition) lorsqu'un nom de fonction est mutilé et devient une chaîne.
  • Plusieurs façons de déclarer des chaînes: une chaîne entre guillemets qq( )peut devenir une chaîne entre guillemets q(); une chaîne délimitée par des parenthèses qq(; ... )peut devenir une chaîne délimitée par un point-virgule qq; ... ;. #les chaînes internes peuvent éliminer les problèmes d'équilibrage en convertissant les éléments en commentaires.

La durée de ce processus peut probablement être quelque peu réduite, même si je doute que la solution d'Ugoren puisse être vaincue.


la source
13
+1 pour les sauts de ligne: uniquement pour la lisibilité ...
Bakuriu
40

HQ9 +

Cela ne manquera jamais de produire le résultat escompté lorsqu'un personnage est supprimé, ce qui donne un score de zéro.

HH

Quand est-ce que je commence?

skeevey
la source
1
Il produit "bonjour, monde" cependant, pas "Bonjour, monde!" comme spécifié.
Paul R
16
Nonsense, la langue a juste été spécifiée à tort sur le esolang wiki;)
skeevey
11
Bon pour vous s'ils ont un compilateur HQ9 + sur l'ordinateur d'interview ... :)
Vous pouvez écrire votre propre compilateur de buggy.
PyRulez
2
@ mbomb007 Cet interpréteur imprime Hello, world!pour la Hcommande.
Dennis
12

Befunge-98 , score 0, 45 octets

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

Essayez-le en ligne!

Bien qu'une solution optimale ait déjà été trouvée (et qu'il n'y ait pas d'égalité), j'ai pensé montrer que cela peut être considérablement simplifié avec Befunge 98.

Explication

Le 20020xxparamètre de manière fiable définit le delta (les étapes du pointeur d'instruction entre les graduations) de (2,0)sorte que, à partir de la première x, seule une commande soit exécutée. Voir cette réponse pour une explication détaillée de la raison pour laquelle cela fonctionne. Ensuite, le code est simplement:

"!dlrow ,olleH"ck,@

Nous mettons d’abord tous les codes de caractères pertinents sur la pile avec "!dlrow ,olleH". Ensuite, ck,signifie imprimer le haut de la pile ( ,), 13 ( cplus 1) fois ( k). @termine le programme.

Martin Ender
la source
11

J, 7 points

Sélection de chaque lettre avec une position impaire:

   _2{.\'HHeellllo,,  wwoorrlldd!!'
Hello, world!
randomra
la source
5
La même chose dans golfscript serait de 4 points:'HHeelllloo,, wwoorrlldd!!'2%
cardboard_box
@cardboard_box N'hésitez pas à le soumettre. :)
randomra
Je vote à nouveau parce que je le comprends et que je n'ai pas l'impression de tricher.
Michael Stern
3

Befunge-93, score 0 (63 octets)

Je sais que ce n'est pas un défi de code-golf, mais j'ai pensé qu'il serait intéressant de voir si la solution Befunge-93 existante pourrait être améliorée en termes de taille. J'avais initialement développé cette technique pour une utilisation dans le même défi Erreur 404 , mais la nécessité d'une charge utile de wrapping dans ce cas a rendu la solution à 3 lignes plus optimale.

Ce n’est pas tout à fait aussi bon que la réponse de Befunge-98 de Martin, mais c’est toujours une réduction assez importante de la solution gagnante Befunge-93.

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

Essayez-le en ligne!

Explication

Il existe deux versions de la charge utile. Pour un programme non modifié, la première commande <l'exécution du programme de droite à gauche, jusqu'à la fin de la ligne, jusqu'à ce qu'il atteigne la vdirection de la seconde ligne et la <dirige vers la gauche dans la version de gauche à droite. de la charge utile.

Une erreur sur la deuxième ligne entraîne le <décalage de la finale vers la gauche et son remplacement par une >orientation du flux vers la droite. La #commande (bridge) n'a rien à franchir. Le code continue donc jusqu'à ce qu'il se termine et atteigne un ^au début de la ligne, le redirigeant vers la première ligne, puis le >dirigeant directement vers la droite. charge utile gauche.

La plupart des erreurs sur la première ligne provoquent simplement un vdécalage des commandes finales , mais cela ne modifie pas le flux principal du code. La suppression de la première <est toutefois légèrement différente. Dans ce cas, le chemin d'exécution se dirige directement vers la charge utile de gauche à droite sur la première ligne.

L'autre cas particulier est la suppression du saut de ligne. Lorsque le code se termine à la fin de la ligne, dans ce cas, il s'agit maintenant de la fin de la seconde ligne. Lorsqu'il rencontre la #commande de droite, il saute par-dessus le >et continue donc directement dans la charge utile de droite à gauche.

En cas de doute, j'ai également testé le script Perl et confirmé que "0 échec sur 63".

James Holderness
la source
0

Gol> <> , score 0, 38 octets

<<H"Hello, world!"/
H"Hello, world!" <

La langue est publiée après le défi.

jimmy23013
la source