Est-ce que le rayon va frapper?

31

Un laser tire un faisceau droit dans l'une des quatre directions orthogonales indiquées par <>^v. Déterminez s'il atteindra la cible Osur une grille rectangulaire.

Chacun d'eux frappera (Vrai):

.....
...O.
.....
...^.
.....

>O.
...

v....
O....

...........
...........
O.........<
...........

Celles-ci manqueront (Faux):

......
......
.^..O.

......
.....>
O.....
......
......


.O.
...
.v.

.....<.
..O....

Entrée: une grille rectangulaire de ., dimensionnée au moins 2x2, avec exactement une cible Oet un laser qui en fait partie <>^v. Les lignes peuvent être une liste de chaînes, un tableau 2D ou une liste imbriquée de caractères, ou une seule chaîne séparée par un retour à la ligne avec un retour à la ligne facultatif.

Sortie : une valeur véridique cohérente si le faisceau laser frappe la cible, et une valeur faussement cohérente s'il manque.

Je considérerai les soumissions qui n'utilisent pas d'expressions régulières (ou de correspondance de chaîne basée sur un modèle intégré) comme une catégorie distincte. Si vous mettez (no regex)après le nom de la langue, votre réponse apparaîtra séparément dans le classement.

Xnor
la source
8
En relation
VisualMelon
6
J'espérais que vous incluriez des miroirs avec /et \ . Peut-être pour une autre question ...
vsz
2
@Mego ... ce qui rend ce défi beaucoup plus simple et permet des approches très différentes.
Martin Ender
2
@Mego, je ne suis pas d'accord; selon cette logique, le défi du monde bonjour est un double de dizaines d'autres défis en même temps. Quoi qu'il en soit, merci de m'avoir informé du pouvoir dont je dispose maintenant pour fermer / rouvrir les défis de golf de code, je n'en étais pas conscient.
aditsu
5
@Mego Bien que cette question soit un cas particulier de l'autre, je ne pense pas que ce soit une dupe car les réponses utilisent des approches totalement différentes. Sur cette question, ils calculent tous le chemin emprunté par le faisceau. Les portails peuvent déplacer le chemin de n'importe où vers n'importe où, ce qui ne semble pas autoriser un raccourci, et les réflecteurs sont difficiles à gérer. Les réponses ici vérifient plutôt ou correspondent à certaines propriétés de la chaîne d'entrée. Bien sûr, vous pouvez copier une réponse de traçage de l'autre défi et supprimer les bits supplémentaires, mais cette méthode est exagérée et donne une solution inutilement longue.
xnor

Réponses:

27

Escargots , 19 octets

\>|\<l|\^u|\vd).,\O

La spécification pour celui-ci peut être implémentée aussi littéralement que possible, aucune réflexion requise.

feersum
la source
6
Pouvez-vous ajouter une explication sur la façon dont cela fonctionne?
Procès de Fund Monica
5
@QPaysTaxes Jusqu'à ce que feersum y arrive, j'espère que cela vous aidera: Snails est un langage de correspondance de motifs 2D. udlrréglez la direction de l'escargot vers le haut / bas / gauche / droite. |fonctionne comme dans les expressions régulières, et )n'a pas besoin d'une parenthèse ouverte correspondante. Ainsi, le code se traduit assez directement par "Trouvez-en un v<>^et définissez la direction de manière appropriée, puis essayez de trouver un O dans cette direction."
FryAmTheEggman
Ouais, ce qu'a dit Eggman. La seule autre chose est que ,c'est comme l' *expression rationnelle.
feersum
13

Rétine, 56 52 42 38 31 30 octets

1 octet enregistré grâce à @ MartinBüttner

O.*<|>.*O|[vO](.*¶)[^O]*[O^]\1

Abuse les propriétés des rectangles. Nécessite une entrée pour avoir une nouvelle ligne de fin.

Essayez-le en ligne

Explication

Cela fonctionne en trois parties:

  • Correspondant à >
  • Correspondant à <
  • Correspondance ^et vc'est parce que la logique ^et vsont vraiment les mêmes, juste les personnages.

Valider <

C'est simple:

O.*<

Cela correspond à un O, éventuellement suivi de caractères non-newline, puis à un<

Valider >

C'est à peu près la même chose que la méthode précédente, sauf l'inverse. D'abord, a >correspond, puisO

Validation ^etv

Cela a été difficile à jouer au golf et a pris la publicité de l'entrée toujours valide. Tout d'abord, nous faisons correspondre si c'est vou un O:

[vO]

Si c'est un ^, le premier caractère rencontré devrait être un O. Donc, cela correspond au premier caractère à faire correspondre. Ensuite, nous comptons le nombre de .s qui le suivent jusqu'à la nouvelle ligne:

(.*\n)

Ensuite, cela peut se diviser en deux parties, je couvrirai la première:

Donc, tout d'abord, nous faisons correspondre jusqu'à ce qui suit O, en utilisant:

[^O]*O

Cela correspond éventuellement à tous les non- Ocaractères jusqu'à ce qu'un Osoit rencontré, si cela réussit, alors cela continue ... sinon, alors ce qui suit se produit ...

Maintenant, il essaie de trouver l' ^utilisation:

[^^]*\^

^est un caractère spécial dans l'expression régulière, il doit donc être échappé. [^^]correspond à tous les caractères sauf ^, cela fonctionne de la même manière que ci-dessus, si cela réussit, alors ce qui suit se produit ...

Alors maintenant, l'un des éléments ci-dessus a réussi, \1vérifie et voit si le groupe de capture d'avant (.*\n), ce groupe de capture a stocké la quantité de .s qu'il y avait après le vou Odepuis avant, alors maintenant \1vérifie simplement si le nombre de points dans le même.

Downgoat
la source
Vous pouvez enregistrer un octet en utilisant au lieu de \n(Retina peut gérer le code source dans ISO 8859-1.)
Martin Ender
@ MartinBüttner pensait que c'était seulement \ n en remplacement, merci pour le conseil!
Downgoat
non, cela fonctionne n'importe où dans le code source. Après avoir divisé le fichier en lignes, la première chose que Retina fait est de remplacer le partout, avant de procéder à une analyse supplémentaire.
Martin Ender
9

Java (pas d'expression régulière), 413 412 246 242 212 211 209 198 198 octets

Participer à des défis de golf en utilisant java a moins de sens que de participer à une course de Formule 1 à vélo, mais je ne pense pas toujours ce qui a du sens.

Voici ma solution java extrêmement longue version Golfed

boolean l(char[][]w){int[]t={},l={};for(int y=0;y<w.length;y++)for(int x=0;x<w[0].length;x++){if(w[y][x]=='O')t=new int[]{x,y};if(w[y][x]=='<')l=new int[]{x,y,1};if(w[y][x]=='>')l=new int[]{x,y,2};if(w[y][x]=='v')l=new int[]{x,y,3};if(w[y][x]=='^')l=new int[]{x,y,4};};return(l[2]==1&&l[1]==t[1]&&l[0]>t[0])||(l[2]==2&&l[1]==t[1]&&l[0]<t[0])||(l[2]==3&&l[0]==t[0]&&l[1]<t[1])||(l[2]==4&&l[0]==t[0]&&l[1]>t[1]);}

et non golfé

boolean l(char[][] w) {
    int[] t = {}, l = {};
    for (int y = 0; y < w.length; y++)
        for (int x = 0; x < w[0].length; x++) {
            if (w[y][x] == 'O')
                t = new int[] { x, y };
            if (w[y][x] == '<')
                l = new int[] { x, y, 1 };
            if (w[y][x] == '>')
                l = new int[] { x, y, 2 };
            if (w[y][x] == 'v')
                l = new int[] { x, y, 3 };
            if (w[y][x] == '^')
                l = new int[] { x, y, 4 };
        }
    ;
    return (l[2] == 1 && l[1] == t[1] && l[0] > t[0])
            || (l[2] == 2 && l[1] == t[1] && l[0] < t[0])
            || (l[2] == 3 && l[0] == t[0] && l[1] < t[1])
            || (l[2] == 4 && l[0] == t[0] && l[1] > t[1]);
}

On dirait que tout mon concept était faux, voici ma solution la plus courte

boolean z(char[][]w){int x=0,y=0,i=0,a=w.length,b=w[0].length;for(;w[y][x]!=79;)if(++y==a){y=0;x++;}for(;i<(a<b?b:a);)if(i<b&w[y][i]==(i<x?62:60)|i<a&w[i][x]==(i++<y?'v':94))return 1<2;return 1>2;}

et version non golfée

oolean z(char[][] w) {
        int x = 0, y = 0, i = 0, a = w.length, b = w[0].length;
        for (; w[y][x] != 79;)
            if (++y == a) {
                y = 0;
                x++;
            }
        for (; i < (a < b ? b : a);)
            if (i < b & w[y][i] == (i < x ? 62 : 60) | i < a
                    & w[i][x] == (i++ < y ? 'v' : 94))
                return 1 < 2;
        return 1 > 2;
    }

EDIT J'ai réécrit le code pour rechercher 'O', maintenant il contient une boucle unique est beaucoup plus courte, et j'ai également utilisé la suggestion @Frozn pour remplacer certains des caractères par leurs valeurs ascii.

En conséquence, 30 octets supplémentaires mord la poussière.

Une autre suggestion de @Frozn, et nous nous rapprochons de quelques octets de la solution Python

Une autre réécriture supprime une boucle et combine deux instructions if

user902383
la source
1
+1 Vous pouvez cependant supprimer l'espace entre returnet (pour enregistrer un octet. L'espace n'est pas nécessaire lorsque votre valeur de retour est entre parenthèses (ou entre guillemets pour les chaînes). Source à partir des conseils Java de golf de code.
Kevin Cruijssen
@KevinCruijssen n'économise pas beaucoup, mais merci :)
user902383
Chaque petit morceau (ou devrais-je dire octet) aide, je suppose. ;) D'ailleurs, je ne pense pas que Java remportera de toute façon un défi de code-golf. J'aime toujours faire des défis de golf de code en Java, d'autant plus que je travaille actuellement avec Java au travail.
Kevin Cruijssen
Vous pouvez remplacer les caractères par leur valeur ASCII: 'O' = 79, '>' = 62, '<' = 60, '^' = 94. Pour 'v' c'est 118 mais cela ne raccourcit pas le code.
Frozn
@Frozn comme Kevin l'a dit, dans chaque octet compte.
user902383
7

MATL (pas d'expression régulière), 26 25 24 22 octets

'>v<^'XJymfX!tZpYswJm)

Essayez-le en ligne!

Version modifiée pour tous les cas de test

Explication

        % Implicitly grab input
'>v<^'  % String literal indicating the direction chars
XJ      % Store in the J clipboard
y       % Copy the input from the bottom of the stack
m       % Check to see which of the direction chars is in the input. The
        % result is a 1 x 4 logical array with a 1 for the found direction char
f       % Get the 1-based index into '>v<^' of this character
X!      % Rotate the input board 90 degrees N times where N is the index. This
        % Way we rotate the board so that, regardless of the direction char,
        % the direction char should always be BELOW the target in the same column
t       % Duplicate
Zp      % Determine if any elements are prime ('O' is the only prime)
Ys      % Compute the cumulative sum of each column
w       % Flip the top two stack elements
J       % Grab '>v<^' from clipboard J
m       % Create a logical matrix the size of the input where it is 1 where
        % the direction char is and 0 otherwise
)       % Use this to index into the output of the cumulative sum. If the 
        % direction char is below 'O' in a column, this will yield a 1 and 0 otherwise
        % Implicitly display the result
Suever
la source
@LuisMendo Maintenant pour comprendre comment se débarrasser deJ
Suever
Je ne connais pas MATL, donc cela peut être une question idiote, mais pourquoi 0 est-il premier?
Neil
3
@Neil C'est une lettre 'O', pas un chiffre 0. Le code ASCII pour la lettre 'O'est79
Luis Mendo
Ugh, je suppose que j'aurais été dupe si vous aviez plutôt cherché des nombres impairs.
Neil
5

CJam (pas d'expression régulière), 25

Les versions antérieures étaient erronées, cela devra faire pour l'instant:

q~_z]{'.-HbI%}f%[HF].&~+,

Essayez-le en ligne

Explication:

q~         read and evaluate the input (given as an array of strings)
_z         copy and transpose
]          put the original grid and transposed grid in an array
{…}f%      map the block to each grid (applying it to each string in each grid)
  '.-      remove all dots (obtaining a string of 0 to 2 chars)
  Hb       convert to base H=17, e.g. ">O" -> 62*17+79=1133
  I%       calculate modulo I=18
[HF]       make an array [17 15]
.&         set-intersect the first array (mapped grid) with 17 and 2nd one with 15
~+         dump and concatenate the results
,          get the array length

J'ai essayé quelques formules mathématiques pour faire la distinction entre les "bonnes" et les "mauvaises" chaînes, et pour chaque type de formule, j'ai essayé de brancher différents nombres. Je me suis retrouvé avec ce qui HbI%précède.

les "bonnes" chaînes pour la grille d'origine sont "> O" et "O <" et elles donnent le résultat 17
"bonnes" chaînes pour la grille transposée sont "vO" et "O ^" et elles donnent le résultat 15
"mauvaises" les chaînes des deux grilles sont: ">", "<", "^", "v", "O", "", "O>", "Ov", "<O", "^ O" et elles donnent les résultats 8, 6, 4, 10, 7, 0, 1, 3, 1, 3

Aditsu
la source
3

Python 3 (pas d'expression régulière), 184 octets.

Hourra pour le piratage eval!

def f(a,o=0,d={},q=''):
 for r in a:
  i=0
  for c in r:d[c]=o,i;i+=1;q=(c,q)[c in'O.']
  o+=1
 z,y=d['O'];e,j=d[q];return eval("z%se and y%sj"%(('><'[q<'v'],'=='),('==',q))[q in'><'])
Morgan Thrapp
la source
3

TSQL (sqlserver 2012) (pas d'expression régulière), 358 octets

DECLARE @ varchar(1000)=
'......'+ CHAR(13)+CHAR(10)+
'......'+ CHAR(13)+CHAR(10)+
'...0..'+ CHAR(13)+CHAR(10)+
'...^..'+ CHAR(13)+CHAR(10)
;

WITH C as(SELECT
number n,SUBSTRING(@,number,1)a,1+min(IIF(SUBSTRING(@,number,1)=char(13),number,99))over()m
FROM master..spt_values
WHERE'P'=type and
SUBSTRING(@,number,1)in('>','<','^','v','0',char(13)))SELECT
IIF(c.n%c.m=d.n%c.m and c.a+d.a in('0^','v0')or
c.n/c.m=d.n/c.m and c.a+d.a in('>0','0<'),1,0)FROM c,c d
WHERE c.n<d.n and char(13)not in(c.a,d.a)

J'ai dû utiliser funky linechange dans la déclaration pour forcer la version en ligne à l'exécuter (l'attribution de valeurs aux variables d'entrée n'affecte pas le calcul de la longueur de toute façon)

Essayez-le en ligne!

t-clausen.dk
la source
2

JavaScript (ES6), 78 octets

s=>s.match(`>.*O|O.*<|(?=v)([^]{${l=s.search`\n`+1}})+O|(?=O)([^]{${l}})+\\^`)

Regexp bien sûr. Il s'est avéré être similaire en principe à la réponse de Ruby.

Neil
la source
2

Rubis, 71 55 54 octets

Solution Regex, ce qui signifie qu'elle sera probablement facilement battue par Retina ou Perl.

Renvoie un numéro d'index (véridique) en cas de correspondance.

Maintenant, avec une astuce similaire à la réponse @Downgoat Retina, correspondant aux faisceaux descendant et montant en même temps.

->m{m=~/>\.*O|O\.*<|(?=[vO])(.{#{??+m=~/\n/}})+[O^]/m}
Valeur d'encre
la source
2

JavaScript (ES6) (pas d'expression régulière), 126 octets

s=>([n,o,l,r,u,d]=[..."\nO<>^"].map(c=>1+s.indexOf(c)),l>o&l-o<n&l%n>o%n||r&&r<o&o-r<n&r%n<o%n||u>o&u%n==o%n||d&&d<o&d%n==o%n)

\nreprésente le caractère de nouvelle ligne littéral.

Neil
la source
2

Clojure (pas d'expression régulière), 293 octets

(defn z[f](let[v(sort(keep-indexed(fn[i v](if(some #{v}[\v\>\<\^\O])[(if(= v\O)\& v)i]))f))l(+(.indexOf f"\n")1)d((nth v 1)0)q((nth v 1)1)p((nth v 0)1)r(=(quot p l)(quot q l))i(> q p)](cond(= d\^)(and i(=(mod(- q p)l)0))(= d\v)(and(not i)(=(mod(- p q)l)0))(= d\>)(and(not i)r):else(and i r))))

Ne se sent pas bien. Solution simple, trouver l'index des caractères correspondants et calculer s'ils sont sur la même ligne.

Vous pouvez l'essayer ici https://ideone.com/m4f2ra

cliffroot
la source
2

Python (pas d'expression régulière), 105 octets

def f(s):t=s.strip('.\n');return not['\n'in t,len(t)%(s.find('\n')+1)!=1,1]['>O<vO^'.find(t[0]+t[-1])//3]

renvoie Vrai ou Faux

D'abord, dépouille '.' et '\ n' à partir des extrémités de sorte que les caractères d'intérêt, '0 <> v ^', soient les premier et dernier caractères.

'>O<vO^'.find(t[0]+t[-1])//3- vérifie si les caractères sont un arrangement potentiellement valide. Évalue à 0 pour «> O» ou «O <», à 1 pour «vO» ou «O ^» et à -1 pour toute autre chose.

'\n'in t- vérifie si les caractères sont dans des lignes différentes,
len(t)%(s.find('\n')+1)!=1- vérifie s'ils sont dans des colonnes différentes, et
1 - est la valeur par défaut

L' notinverse le résultat sélectionné dans la liste, donc l' returnexpression est équivalente à:

t[0]+t[-1] in '>0<' and '\n' not in t or t[0]+t[-1] in 'vO^' and len(t)%(s.find('\n')+1)==1
RootTwo
la source
2

Julia (pas d'expression régulière), 98

a->(c=rotr90(a,findlast("i1Q/",sum(a-46)));
    f(n)=find(any(c.!='.',n));b=c[f(2),f(1)];
    (b'*b)[1]==97)

Fonction fonctionnant sur un tableau de caractères, normalisant par rotation, supprimant les lignes et les colonnes ne contenant que des points par indexation de plage et enfin vérifiant l'emplacement de `` O '' en tenant compte si le reste b est un vecteur de colonne ou de ligne utilisant la multiplication matricielle.

Essayez-le en ligne

mschauer
la source
1

Python 2 (pas d'expression régulière), 268 octets

import numpy
def q(i):
 s=numpy.asmatrix(i)
 for n in s:
  n=n.tolist()[0]
  try:
   a=n.index("0")
   if n.index(">")<a or n.index("<")>a:return 1
  except:0
 for n in range(len(i)):
  c=[x[0] for x in s[:,n].tolist()]
  try:
   a=c.index("0")
   if c.index("v")<a or c.index("^")>a:return 1
  except:0
 return 0

Les valeurs Truthy et Falsy renvoyées par la fonction sont respectivement 1 et 0.

Je n'ai pas encore eu l'occasion de jouer au golf. Honnêtement, je n'ai pas trop d'espoir pour celui-ci ...

Toutes les suggestions seraient grandement appréciées!

Daniel
la source
1

C # (sans regex), 282 octets

bool F(char[,]b){int k=0,l=1,m=1,n=0,o=0;for(int x=0;x<b.GetLength(0);x++)for(int y=0;y<b.GetLength(1);y++){char i=b[x,y];if(i=='O'){k=x;l=y;}if(new[]{'<','>','^','v'}.Contains(i)){m=x;n=y;o=i;}}return(o==60&&k==m&&l<n)||(o==62&&k==m&&l>n)||(o==94&&l==n&&k<m)||(o==118&&l==n&&k>m);}

Fonctionne comme la version java mais transposée et réduite

Développé (explication incluse):

bool F(char[,] b)
{
    // declare variables for goal x, goal y, laser x, laser y, and laser direction respectively (laser direction is char code for directions)
    int k = 0, l = 0, m = 0, n = 0, o = 0;
    // go through each cell
    for (int x = 0; x < b.GetLength(0); x++)
    {
        for (int y = 0; y < b.GetLength(1); y++)
        {
            // get cell contents
            char i = b[x, y];
            // set goal position if goal
            if (i == 'O')
            {
                k = x;
                l = y;
            }
            // set laser position and direction if laser
            if (new[]{ '<', '>', '^', 'v' }.Contains(i))
            {
                m = x;
                n = y;
                o = i;
            }
        }
    }
    // check everything is on the same line and in right direction
    return (o == 60 && k == m && l < n) ||
           (o == 62 && k == m && l > n) ||
           (o == 94 && l == n && k < m) ||
           (o == 118 && l == n && k > m);
}
RedLaser
la source
0

C (ANSI) (pas d'expression régulière), 237 octets

#define l b[1][i]
main(i,b,c,d,x,y,z,p)char **b;{for(y=z=i=0,x=1;z<2&&(l==10?x=0,++y:1);i++,x++)if(l>46){if(l!=79)p=l;if(!z++)c=x,d=y;}i--;x--;z=(c==x)*((p=='v')*(l==79)+(p==94)*(l==p))+(d==y)*((p==60)*(l==p)+(p==62)*(l==79));return z;}

Étendu:

#define l b[1][i]
main(i,b,c,d,x,y,z,p)char **b;{
    for(y=z=i=0,x=1;z<2&&(l==10?x=0,++y:1);i++,x++)
        if(l>46){if(l!=79)p=l;if(!z++)c=x,d=y;}
    i--;x--;
    z=(c==x)*((p=='v')*(l==79)+(p==94)*(l==p))+(d==y)*((p==60)*(l==p)+(p==62)*(l==79));
    printf("%i\n",z);
    return z;
}

Je pense que j'ai adopté une approche décemment différente par rapport aux implémentations Java ou C #. J'ai obtenu les coordonnées du «O» et de la flèche ((c, d) et (x, y)), puis je les ai comparées pour voir si la flèche pointait dans la bonne direction.

Renvoie 0 si faux et 1 si vrai

dj0wns
la source
0

Grime v0.1 , 31 octets

n`\>.*a|a.*\<|\v/./*/a|a/./*/\^

Pas une solution très intéressante. Imprime 1pour les instances véridiques et les 0fausses. Essayez-le en ligne!

Explication

Nous recherchons simplement le rectangle d'entrée pour un motif de taille minimale (n × 1 ou 1 × n) qui contient le laser et la cible dans le bon ordre. Le n`drapeau fait que l'interprète imprime le nombre de correspondances, dont il y en aura toujours au plus une. Le reste de la ligne se compose de quatre motifs séparés par des |caractères, ce qui signifie un OU logique: un rectangle est mis en correspondance s'il correspond à l'un des motifs. Les modèles fonctionnent comme suit:

\>.*a    Literal ">", horizontal row of any chars, one alphabetic char
a.*\<    One alphabetic char, horizontal row of any chars, literal "<"
\v/./*/a Literal "v", on top of vertical column of any chars, on top of one alphabetic char
a/./*/\^ One alphabetic char, on top of vertical column of any chars, on top of literal "^"
Zgarb
la source