Laser de Schrödinger


24

Marre d' expérimenter sur de minuscules animaux domestiques , Erwin Schrödinger, lauréat du prix Nobel, a décidé de trouver le laser le plus proche et de lui tirer dessus. Parce que ... la science!

La description

Vous recevrez deux points que le laser traverse et la taille d'un faisceau laser, et vous devez déterminer où le faisceau laser doit être allé, aurait pu aller et n'aurait pas pu aller.

Le faisceau laser peut être horizontal, vertical ou diagonal. Pour un faisceau laser de taille 1, ils ressemblent respectivement à ceci:

       #  #
       #   #
#####  #    #
       #     #
       #      #

Le faisceau laser diagonal peut également être inversé. Les faisceaux laser de taille 2 ressemblent à ceci:

       ###  ##
#####  ###  ###
#####  ###   ###
#####  ###    ###
       ###     ##

En général, pour obtenir un faisceau laser de taille (n), il suffit de prendre le faisceau laser de taille (n-1) et d'ajouter un faisceau laser de taille (1) des deux côtés. Comme dernier exemple, voici tous les faisceaux laser possibles de taille 3, montrés sur la même "carte":

###.....#####.....##
####....#####....###
#####...#####...####
.#####..#####..#####
..#####.#####.#####.
...###############..
....#############...
.....###########....
####################
####################
####################
####################
####################
.....###########....
....#############...
...###############..
..#####.#####.#####.
.#####..#####..#####
#####...#####...####
####....#####....###

Cette "planche" aura toujours des dimensions de 20x20 (en caractères).

Contribution

Votre programme recevra cinq entiers en entrée. Ils sont, dans l'ordre, x 1 , y 1 , x 2 , y 2 et la taille du faisceau laser. Ils doivent être pris exactement dans cet ordre. Si vous le souhaitez, vous pouvez prendre les paires ordonnées (x, y) comme un tableau, un tuple, une liste ou tout autre type de données intégré qui stocke deux valeurs.

Les deux points donnés en entrée seront dans le tableau et ils sont garantis distincts (c'est-à-dire que les deux points ne seront jamais identiques). La taille du faisceau laser est liée à 1 ≤ size < 20. Il y aura toujours au moins un faisceau laser possible qui passera par les deux points.

Sortie

Votre programme doit produire une grille 20x20 des caractères suivants:

  • # si chaque faisceau laser possible qui passe par les deux points passe également par ce point.
  • . s'il n'y a pas de faisceau laser qui passe par les deux points et ce point.
  • ? si certains, mais pas tous, des faisceaux laser possibles passent par ce point.
  • Xs'il s'agit de l'un des deux points d'entrée d'origine (cela remplace le #).

Cas de test

7, 7, 11, 3, 1

..............#.....
.............#......
............#.......
...........X........
..........#.........
.........#..........
........#...........
.......X............
......#.............
.....#..............
....#...............
...#................
..#.................
.#..................
#...................
....................
....................
....................
....................
....................

18, 18, 1, 1, 2

#??.................
?X??................
??#??...............
.??#??..............
..??#??.............
...??#??............
....??#??...........
.....??#??..........
......??#??.........
.......??#??........
........??#??.......
.........??#??......
..........??#??.....
...........??#??....
............??#??...
.............??#??..
..............??#??.
...............??#??
................??X?
.................??#

10, 10, 11, 10, 3

?????..????????..???
??????.????????.????
????????????????????
????????????????????
.???????????????????
..??????????????????
????????????????????
????????????????????
????????????????????
????????????????????
??????????XX????????
????????????????????
????????????????????
????????????????????
????????????????????
..??????????????????
.???????????????????
????????????????????
????????????????????
??????.????????.????

3, 3, 8, 10, 4

??????????..........
??????????..........
??????????..........
???X??????..........
???##?????..........
???###????..........
????###????.........
.????###????........
..????###????.......
..?????##?????......
..??????X??????.....
..??????????????....
..???????????????...
..????????????????..
..?????????????????.
..??????????????????
..??????????????????
..????????.?????????
..????????..????????
..????????...???????

Les cas de test ont été générés avec le script Ruby suivant, situé à l'intérieur d'un extrait de pile pour conserver l'espace vertical.

Règles

  • Votre programme doit être capable de résoudre chacun des cas de test en moins de 30 secondes (sur une machine raisonnable). Il s'agit plus d'une vérification de santé mentale, car mon programme de test Ruby a résolu tous les cas de test presque instantanément.

  • C'est le , donc la solution la plus courte l'emporte.


2
La terminologie utilisée ici m'a déclenché au départ. Je crois que le laser fait normalement référence à un appareil qui produit des faisceaux laser . Ce que vous représentez ici, ce sont vraiment les poutres, non? Ce n'est pas censé être une représentation du laser réel, quel serait l'appareil générant les faisceaux?
Reto Koradi

2
Le dernier cas de test semble faux. Un laser de taille 4 doit avoir une largeur de 9 pixels. La piste verticale devrait être au moins aussi large, mais en fait elle est plus étroite.
Level River St

1
@steveverrill La taille 4 mesure 7 pixels de large. La largeur en pixels est 2 * size - 1. La taille 1 est de 1 pixel, la taille 2 est de 3 pixels, la taille 3 est de 5 pixels (voir l'exemple ci-dessus), la taille 4 est de 7 pixels.
Reto Koradi

2
Je ne vois pas comment Schrodinger est lié à ce défi.
user12205

1
@JonasDralle Encore une fois, la limite de temps est principalement juste un contrôle de santé mentale, et presque chaque soumission devrait se terminer en beaucoup moins de temps que cela.
Poignée de porte

Réponses:


5

C, 291 280 277 265 octets

x,y,A,C,B,D,a,c,b,d,w,s,t;T(i){return abs(i)<2*w-1;}U(j,k){s+=T(j-k)*T(j)*T(k);t*=T(j-k)*j*k<1;}main(){for(scanf("%i%i%i%i%i",&a,&b,&c,&d,&w);y<20;y+=!x)s=0,t=1,U(A=a-x,C=c-x),U(B=b-y,D=d-y),U(A-B,C-D),U(A+B,C+D),putchar((x=++x%21)?".?#x"[!!s+t+(!A*!B+!C*!D)]:10);}

Peut être compilé / exécuté en utilisant:

gcc laser.c -o laser && echo "10 10 11 10 3" | ./laser

Ci-dessous, le même code avec des espaces et des commentaires explicatifs:

// Integers...
x,y,A,C,B,D,a,c,b,d,w,s,t;

// Is true if i is in range (of something)
T(i){return abs(i)<2*w-1;}

// Tests if lasers (horizontal, vertical, diagonal, etc) can/must exist at this point
// T(j-k) == 0 iff the laser of this direction can exist
// s += 1 iff this laser direction can pass through this point
// t *= 1 iff this laser direction must pass through this point
U(j,k){
    s+=T(j-k)*T(j)*T(k);
    t*=T(j-k)*j*k<1;
}

main(){ 
    // Read input; p0=(a,b), p1=(c,d)
    for(scanf("%i%i%i%i%i",&a,&b,&c,&d,&w); y<20; y+=!x)

        // A, B, C and D represent delta-x and delta-y for each points
        // e.g.: if we're processing (2,3), and p0=(4,5), A=4-2, B=5-3
        // s != 0 iff (x,y) can have some laser through it
        // t == 1 iff all lasers pass through (x,y)
        // (!A*!B+!C*!D) == 1 iff (x,y) is either p0 or p1  
        s=0,t=1,U(A=a-x,C=c-x),U(B=b-y,D=d-y),U(A-B,C-D),U(A+B,C+D),
        putchar((x=++x%21)?".?#x"[!!s+t+(!A*!B+!C*!D)]:10);
}

1
U(int j,int k)-> U(j,k); '\n'-> 10.
user12205

1
k<=0->k<1
user12205

Bons points. Je voterais si je le pouvais!
André Harder

4

C, 302 octets

b[400],x,y,s,t,w,d,e,g,k;f(u,v){d=u*x+v*y;e=u*s+v*t;if(e<d)k=e,e=d,d=k;for(k=0;k<400&d+w>e;++k)g=k%20*u+k/20*v,b[k]|=g>e-w&g<d+w|(g<d|g>e)*2;}main(){scanf("%d%d%d%d%d",&x,&y,&s,&t,&w);w=2*w-1;f(1,0);f(0,1);f(1,1);f(1,-1);b[y*20+x]=4;b[t*20+s]=4;for(k=0;k<400;)putchar(".#.?X"[b[k]]),++k%20?0:puts("");}

L'entrée est tirée de stdin, lisant les 5 nombres dans l'ordre défini.

Avant l'étape finale de réduction de la taille:

#include <stdio.h>
#include <stdlib.h>

int b[400], x, y, s, t, w, d, e, g, k;

void f(int u, int v) {
  d = u * x + v * y;
  e = u * s + v * t;
  if (e < d) k = e, e = d, d = k;
  if (d + w > e) {
    for (k = 0; k < 400; ++k) {
      g = u * (k % 20) + v * (k / 20);
      if (g > e - w && g < d + w) b[k] |= 1;
      if (g < d || g > e) b[k] |= 2;
    }
  }
}

int main() {
  scanf("%d%d%d%d%d", &x, &y, &s, &t, &w);
  w = 2 * w - 1;
  f(1, 0); f(0, 1); f(1, 1); f(1, -1);
  b[y * 20 + x] = 4;
  b[t * 20 + s] = 4;
  for (k = 0; k < 400; ) {
     putchar(".#.?X"[b[k]]);
     ++k % 20 ? 0 : puts("");
  }
}

Quelques explications sur les étapes clés:

  • Le tableau bcontient l'état / résultat. Le bit 0 sera défini pour tous les pixels pouvant être atteints par un faisceau. Le bit 1 sera défini pour tous les pixels qui ne sont pas couverts par tous les faisceaux.
  • La fonction fest appelée pour les 4 directions (verticale, horizontale, les deux diagonales). Ses arguments spécifient le vecteur normal de la direction.
  • En fonction f:
    • La distance des deux points d'entrée par rapport à la direction est calculée ( det e) comme le produit scalaire du point avec le vecteur normal transmis.
    • Les distances sont permutées si nécessaire de manière à ce qu'elles dsoient toujours inférieures ou égales e.
    • Si la différence entre det eest supérieure à la largeur du faisceau, aucun faisceau n'est possible dans cette direction.
    • Sinon, faites une boucle sur tous les pixels. Définissez le bit 0 si le pixel est accessible par n'importe quel faisceau et le bit 1 s'il n'est pas couvert par tous les faisceaux.
  • Marquez les deux points d'entrée avec la valeur 4. Puisque nous avons utilisé les bits 0 et 1 pour suivre l'état, ce qui donne les valeurs 0 à 3, il s'agit de la plus petite valeur inutilisée.
  • Faites une boucle sur les pixels bet convertissez les valeurs comprises entre 0 et 4 en leur caractère correspondant lors de leur impression.

vous pouvez probablement économiser un peu en mettant la dernière ligne de code dans l'incrémenteur dans cette forboucle
pas que Charles
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.