152 votes

Golf de code : Lasers

Le défi

Le plus court code par le nombre de caractères à l'entrée d'une représentation en 2D d'un conseil d'administration et à la sortie de "vrai" ou "faux" selon l'entrée.

Le conseil d'administration est composé de 4 types de tuiles:

 # - A solid wall
 x - The target the laser has to hit
 / or \ - Mirrors pointing to a direction (depends on laser direction)
 v, ^, > or < - The laser pointing to a direction (down, up, right and left respectively)

Il y a seulement un laser et seulement une cible. Les murs doivent former un rectangle solide de toute taille, où le laser et la cible sont placés à l'intérieur. Les murs à l'intérieur de la chambre sont possibles.

Rayon Laser coups de feu et se déplace à partir de son origine à la direction de pointage. Si un rayon laser touche le mur, il s'arrête. Si un rayon laser frappe un miroir, elle rebondit de 90 degrés de la direction du miroir. Les miroirs sont à double sens, de la signification des deux côtés sont de ğ réflexion ğ et peut rebondir un rayon de deux façons. Si un rayon laser frappe le laser (^v><) lui-même, il est traité comme un mur (faisceau laser détruit le projecteur et peut donc ne jamais toucher la cible).

Des cas de Test

Entrée:
##########
 # / \ #
 # #
 # \ x#
 # > / #
 ########## 
Sortie:
vrai

Entrée:
##########
 # v x #
 # / #
 # /#
 # \ #
##########
Sortie: 
faux

Entrée:
#############
 # # #
 # > # #
 # # #
 # # x #
 # # #
#############
Sortie:
faux

Entrée:
##########
 #/\/\/\ #
 #\\//\\\ #
#//\/\/\\#
#\/\/\/x^#
##########
Sortie:
vrai

Code de comptage d'entrée/de sortie (j'.e programme complet).

78voto

mob Points 61524

Perl, 166 160 caractères

Perl, 251 248 246 222 214 208 203 201 193 190 180 176 173 170 166 --> 160 caractères.

Solution avait 166 coups lors de ce concours est terminé, mais A. Rex a trouvé un couple de façons de se raser plus de 6 caractères:

s!.!$t{$s++}=$&!ge,$s=$r+=99for<>;%d='>.^1<2v3'=~/./g;($r)=grep$d|=$d{$t{$_}},%t;
{$_=$t{$r+=(1,-99,-1,99)[$d^=3*/\\/+m</>]};/[\/\\ ]/&&redo}die/x/?true:false,$/

La première ligne de charge de la saisie en %t, un tableau de bord où $t{99*i+j} détient le caractère à la ligne i,colonne j. Ensuite,

%d=split//,'>.^1<2v3' ; ($r)=grep{$d|=$d{$t{$_}}}%t

il recherche les éléments d' %t pour un personnage qui correspond > ^ < ou v, et simultanément définit $d à une valeur comprise entre 0 et 3 qui indique la direction initiale du faisceau laser.

Au début de chaque itération de la boucle principale, nous mettons à jour $d si le faisceau est actuellement sur un miroir. Utilise XOR par 3 donne le comportement correct pour un \ miroir et utilise XOR par 1 donne le comportement correct pour un / miroir.

$d^=3*/\\/+m</>

Ensuite, la position actuelle $r est mis à jour accoring à la direction du courant.

$r+=(1,-99,-1,99)[$d] ; $_ = $t{$r}

Nous attribuer le caractère à la position actuelle à l' $_ de faire une utilisation pratique de la correspondance des opérateurs.

/[\/\\ ]/ && redo

Continuer si nous sommes sur un espace vide ou un miroir de caractère. Sinon, nous résilier true si nous sommes sur la cible ($_ =~ /x/) et false sinon.

Limitation: ne peut pas travailler sur les problèmes avec plus de 99 colonnes. Cette limitation pourrait être retiré à la charge de plus de 3 caractères,

75voto

hobbs Points 71946

Perl, 177 Caractères

Le premier saut de ligne peut être supprimée; les deux autres sont obligatoires.

$/=%d=split//,' >/^\v';$_=<>;$s='#';{
y/v<^/>v</?do{my$o;$o.=" 
"while s/.$/$o.=$&,""/meg;y'/\\'\/'for$o,$s;$_=$o}:/>x/?die"true
":/>#/?die"false
":s/>(.)/$s$d{$1}/?$s=$1:1;redo}

Explication:

$/ = %d = (' ' => '>', '/' => '^', '\\' => 'v');

Si un droit de déplacement de la traverse dans un {vide de l'espace, coudé à miroir, le miroir inclinable} il devient un {droite de déplacement de la poutre, le déplacement de la poutre, en bas de déplacement de la poutre}. Initialiser $/ le long du chemin, heureusement "6" n'est pas une entrée valide char.

$_ = <>;

Lire le conseil d'administration en $_.

$s="#";

$s est le symbole de ce que le faisceau est assis sur le dessus de maintenant. Depuis le laser de l'émetteur est d'être traité comme un mur, l'ensemble de ce mur pour commencer.

if (tr/v<^/>v</) {
  my $o;
  $o .= "\n" while s/.$/$o .= $&, ""/meg;
  tr,/\\,\\/, for $o, $s;
  $_ = $o;
}

Si le faisceau laser est orienté, en quelque manière, sauf en droit, pivoter son symbole, puis faites pivoter l'ensemble du conseil d'administration en place (aussi la rotation des symboles pour les miroirs). C'est un angle de 90 ° rotation à gauche, accompli de manière efficace en inversant les lignes lors de la transposition des lignes et des colonnes, un peu diabolique s///e avec des effets secondaires. Dans le ont joué au golf de code, le tr est écrit sous la forme y''' ce qui me permet de sauter backslashing une barre oblique inverse.

die "true\n" if />x/; die "false\n" if />#/;

Terminer avec le bon message, si l'on touche la cible ou sur un mur.

$s = $1 if s/>(.)/$s$d{$1}/;

Si il y a un espace vide devant le laser, aller de l'avant. Si il y a un miroir devant le laser, aller de l'avant et faire pivoter la poutre. Dans les deux cas, mettre le sauver "symbole" dans l'ancien faisceau emplacement, et de mettre la chose que nous juste écrasait sauvé symbole.

redo;

Répétez jusqu'à la fin. {...;redo} est deux personnages moins de for(;;){...} et trois de moins que while(1){...}.

39voto

strager Points 41713

C89 (209 caractères)

#define M(a,b)*p==*#a?m=b,*p=1,q=p:
*q,G[999],*p=G;w;main(m){for(;(*++p=getchar())>0;)M(<,-1)M
(>,1)M(^,-w)M(v,w)!w&*p<11?w=p-G:0;for(;q+=m,m=*q&4?(*q&1?
-1:1)*(m/w?m/w:m*w):*q&9?!puts(*q&1?"false":"true"):m;);}

Explication

Cette monstruosité sera probablement difficile à suivre si vous ne comprenez pas C. Juste un avertissement.

#define M(a,b)*p==*#a?m=b,*p=1,q=p:

Cette petite macro vérifie si le caractère courant (*p) est égale à a est dans le formulaire de caractère (*#a). Si elles sont égales, définir le vecteur de mouvement d' b (m=b), la marque de ce personnage comme un mur (*p=1), et de définir le point de départ de l'emplacement actuel (q=p). Cette macro inclut le "else".

*q,G[999],*p=G;
w;

Déclarer des variables. * q est la lumière de l'emplacement actuel. * G est le plateau de jeu comme un tableau 1D. * p est la lecture actuelle de l'emplacement lors du remplissage d' G. * w est la largeur de la planche.

main(m){

Évident main. m est une variable contenant le vecteur de mouvement. (C'est un paramètre main comme une optimisation.)

    for(;(*++p=getchar())>0;)

Boucle par tous les personnages, le remplissage d' G l'aide p. Passez G[0] comme une optimisation (pas besoin de gaspiller un caractère d'écriture p de nouveau dans la troisième partie de l' for).

        M(<,-1)
        M(>,1)
        M(^,-w)
        M(v,w)

Ci macro pour définir le lazer, si possible. -1 et 1 correspondent à gauche et à droite, respectivement, et -w et w en haut et en bas.

        !w&*p<11
            ?w=p-G
            :0;

Si le caractère courant est un fin-de-marqueur de ligne (ASCII 10), définissez la largeur si elle n'a pas déjà été créé. Le sauté G[0] nous permet d'écrire w=p-G au lieu de w=p-G+1. Aussi, cela se termine au large de la ?: chaîne de l' M'.

    for(;
        q+=m,

Déplacer la lumière par le vecteur de mouvement.

        m=
        *q&4
            ?(*q&1?-1:1)*(
                m/w?m/w:m*w
            )

Refléter le vecteur de mouvement.

            :*q&9
                ?!puts(*q&1?"false":"true")
                :m
        ;

Si c'est un mur ou x, fermer avec le message approprié (m=0 se termine la boucle). Sinon, ne rien faire (noop; m=m)

    );
}

36voto

Platinum Azure Points 22380

Je serais prêt à parier que les gens ont été en attente pour celui-ci pendant un LOOOOONG moment. (Que voulez-vous dire, le défi est plus et personne ne s'en soucie plus?)

Voilà... je présente ici une solution

Befunge-93!

Il pèse un énorme 973 charaters (ou 688 si vous êtes de bienfaisance assez pour ignorer les espaces blancs, qui n'est utilisé que pour la mise en forme et n'a rien dans le code).

Mise en garde: j'ai écrit ma propre Befunge-93 interprète en Perl, il y a peu, et c'est malheureusement tout ce que j'ai vraiment eu le temps nécessaire pour faire le test. Je suis raisonnablement confiant dans sa justesse en général, mais il pourrait avoir une drôle de limitation quant à l'EOF: Depuis Perl <> opérateur retourne undef à la fin du fichier, c'est traité comme un 0 dans le contexte numérique. Pour C implémentations basées où EOF a une valeur différente (-1 dire), ce code peut ne pas fonctionner.

003pv   >~v>  #v_"a"43g-!#v_23g03p33v>v
>39#<*v   ::   >:52*-!v   >"rorrE",vg2*
######1   >^vp31+1g31$_03g13gp vv,,<15,
    a#3     >0v       vp30+1g30<>,,#3^@
######p $     0vg34"a"<   >       >vp
^<v>  > ^   p3<>-#v_:05g-!|>:15g-!| $
 >     v^     <   <   <   >^v-g52:< $ 
  v _  >52*"eslaf",,vv|-g53:_      v   
  : ^-"#">#:< #@,,,,<<>:43p0 v0 p34< 
  >">"-!vgv<  ^0p33g31p32-1g3<       
 ^     <#g1|-g34_v#-g34_v#-g34"><v^"<<<<
    v!<^<33>13g1v>03g1-v>03g1+03p$v  $$
>^  _#-v 1>g1-1v>+13pv >03p       v  pp
^_:"^"^#|^g30 <3#   $<           $<>^33
 ^!-"<":<>"v"v^># p#$<>            $^44
^      >#^#_ :" "-#v_ ^   >         ^gg
v  g34$<   ^!<v"/":< >$3p$^>05g43p$ ^55
 >,@   |!-"\"  :_$43g:">"-!|>      ^$32
 *v"x":<      >-^    ^4g52<>:"^" -#v_^
 5>-!#v_"ror"vv$p34g51:<>#|  !-"<":<#|
 ^2,,, ,,"er"<>v      #^^#<>05g43p$$^>^
      >52*"eurt",,,,,@>15g4 3p$$$$  ^#
>:"v"\:"<"\: "^"   -!#^_-!#^_-!      ^
               >                       ^

Explication

Si vous n'êtes pas familier avec le Befunge la syntaxe et le fonctionnement, vérifier ici.

Befunge est une pile, de la langue, mais il y a des commandes qui permettent d'écrire des caractères dans la Befunge code. J'en profite en deux endroits. Tout d'abord, je copie l'ensemble de l'entrée sur le Befunge conseil, mais situé à quelques lignes au-dessous de la réelle le code écrit. (Bien sûr, ce n'est jamais réellement visible lorsque le code s'exécute.)

L'autre endroit est à proximité de la le coin supérieur gauche:

######
    a#
######

Dans ce cas, le domaine, je l'ai souligné ci-dessus est là que j'ai stocker un couple de coordonnées. La première colonne de la rangée du milieu, il est l'endroit où je stocke les coordonnées x de la "position du curseur"; la deuxième colonne est l'endroit où je stocke la coordonnée; les deux colonnes suivantes sont pour le stockage de l'x et y les coordonnées du faisceau laser de la source quand c'est trouvé, et la dernière colonne (avec le " un " caractère) est finalement écrasé à contenir l'actuelle direction du faisceau, ce qui évidemment change à mesure que le faisceau du chemin est tracé.

Le programme commence par placer (0,27) que la position initiale du curseur. Puis à l'entrée est de lire les caractères un à un et placé dans la position du curseur, les retours à la ligne simplement la coordonnée à l'augmentation et à la coordonnée x pour revenir à 0, comme pour un vrai retour chariot. Finalement, le fnud est lu par l'interprète et 0 la valeur du caractère est utilisé pour signaler la fin de l'entrée et de passer au laser itération des étapes. Lorsque le laser caractère [<>^v] est lu, qui est également copié dans la mémoire référentiel (sur le 'a') et ses coordonnées sont copiés dans les colonnes à la gauche.

Le résultat final de tout cela est que la totalité du fichier est en fait copié dans le Befunge code, un peu en-dessous du code traversés.

Par la suite, le faisceau emplacement est recopié dans le curseur endroits, et l'itération suivante est effectuée:

  • Vérifier l'actuelle direction du faisceau et de l'incrémenter ou décrémenter les coordonnées du curseur de façon appropriée. (Je le fais d'abord pour éviter d'avoir à traiter avec le coin de cas du faisceau laser à droite sur le premier coup.)
  • Lire le caractère à l'emplacement.
  • Si le caractère "#", mettre de saut de ligne et les "faux" sur la pile, de l'impression, et à la fin.
  • Le comparer à l'ensemble de la poutre caractères [<>^v]; si il y a un match, aussi de l'impression de "faux\n" et à la fin.
  • Si le caractère est un espace vide de la pile et de continuer.
  • Si le personnage est un slash, obtenir de la direction du faisceau sur la pile et de le comparer à chacun de la direction personnages à tour de rôle. Lorsque l'on est trouvé, la nouvelle direction est stocké au même endroit dans le code et la boucle se répète.
  • Si le caractère est une barre oblique inverse, faire essentiellement la même chose que ci-dessus (à l'exception de la configuration appropriée pour la barre oblique inverse).
  • Si le caractère est "x", nous avons touché la cible. Print "vrai\n" et la sortie.
  • Si le personnage est aucun de ces, print "erreur\n" et la sortie.

Si il y a assez de demande pour cela, je vais essayer de le point exactement où dans le code, tout cela est accompli.

29voto

Brian Points 82719
<h1>F #, 36 lignes, très lisibles<p>OK, juste pour obtenir une réponse là :</p><pre><code></code></pre><p>Échantillons :</p><pre><code></code></pre></h1>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X