Laser di Schrödinger


24

Stufo di sperimentare piccoli animali domestici , il vincitore del premio Nobel Erwin Schrödinger ha deciso di trovare il laser più vicino e sparargli contro le cose. Perché ... scienza!

Descrizione

Ti verranno dati due punti attraverso i quali passa il laser e le dimensioni di un raggio laser, e devi determinare dove deve essere passato il raggio laser , potrebbe esserci andato e non avrebbe potuto andare.

Il raggio laser può essere orizzontale, verticale o diagonale. Per un raggio laser di dimensione 1, assomigliano rispettivamente a questo:

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

Il raggio laser diagonale può anche essere capovolto. I raggi laser di dimensione 2 si presentano così:

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

In generale, per ottenere un raggio laser di dimensioni (n), è sufficiente prendere il raggio laser di dimensioni (n-1) e aggiungere un raggio laser di dimensioni (1) su entrambi i lati. Come ultimo esempio, qui ci sono tutti i possibili raggi laser di dimensione 3, mostrati sulla stessa "scheda":

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

Questa "tavola" avrà sempre dimensioni di 20x20 (in caratteri).

Ingresso

Al tuo programma verranno dati cinque numeri interi come input. Sono, nell'ordine, x 1 , y 1 , x 2 , y 2 e le dimensioni del raggio laser. Devono essere presi esattamente in quell'ordine. Se lo si desidera, è possibile prendere le coppie ordinate (x, y) come una matrice, tupla, elenco o altro tipo di dati incorporato che memorizza due valori.

Entrambi i due punti dati come input saranno all'interno del tabellone e sono garantiti per essere distinti (cioè i due punti non saranno mai gli stessi). La dimensione del raggio laser è legata a 1 ≤ size < 20. Ci sarà sempre almeno un possibile raggio laser che attraversa entrambi i punti.

Produzione

Il tuo programma deve generare una griglia 20x20 dei seguenti caratteri:

  • # se ogni possibile raggio laser che passa attraverso i due punti attraversa anche questo punto.
  • . se non c'è raggio laser che attraversa i due punti e questo punto.
  • ? se alcuni, ma non tutti, i possibili raggi laser passano attraverso questo punto.
  • Xse questo è uno dei due punti di input originali (questo sostituisce il #).

Casi 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??????.....
..??????????????....
..???????????????...
..????????????????..
..?????????????????.
..??????????????????
..??????????????????
..????????.?????????
..????????..????????
..????????...???????

I casi di test sono stati generati con il seguente script Ruby, situato all'interno di un frammento di stack per conservare lo spazio verticale.

Regole

  • Il tuo programma deve essere in grado di risolvere ciascuno dei casi di test in meno di 30 secondi (su una macchina ragionevole). Questo è più di un controllo di integrità, poiché il mio programma di test Ruby ha risolto quasi tutti i casi di test quasi istantaneamente.

  • Questo è , quindi vince la soluzione più breve.


2
La terminologia usata qui mi ha fatto inciampare inizialmente. Credo che il laser si riferisca normalmente a un dispositivo che produce raggi laser . Quello che stai rappresentando qui sono davvero i raggi, giusto? Questa non dovrebbe essere una rappresentazione del laser reale, quale sarebbe il dispositivo che genera i raggi?
— Reto Koradi,

2
L'ultimo test case sembra sbagliato. Un laser di dimensione 4 dovrebbe essere largo 9 pixel. La traccia verticale dovrebbe essere almeno così ampia, ma in realtà è più stretta.
— Level River St

1
@steveverrill La dimensione 4 è larga 7 pixel. La larghezza in pixel è 2 * size - 1. La dimensione 1 è 1 pixel, la dimensione 2 è 3 pixel, la dimensione 3 è 5 pixel (vedi esempio sopra), la dimensione 4 è 7 pixel.
— Reto Koradi,

2
Non vedo come Schrodinger sia legato a questa sfida.
— user12205

1
@JonasDralle Anche in questo caso, il limite di tempo è per lo più solo un controllo di integrità e quasi ogni invio dovrebbe essere completato in un tempo molto inferiore a quello.
— Maniglia della porta

Risposte:


5

C, 291 280 277 265 byte

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);}

Può essere compilato / eseguito usando:

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

Di seguito, lo stesso codice con spazi bianchi e commenti esplicativi:

// 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

Punti buoni. Vorrei votare se potessi!
— André Harder,

4

C, 302 byte

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'input viene preso dallo stdin, leggendo i 5 numeri nell'ordine definito.

Prima della fase di riduzione della dimensione finale:

#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("");
  }
}

Alcune spiegazioni sui passaggi chiave:

  • schieramento b contiene lo stato / il risultato. Il bit 0 verrà impostato per tutti i pixel che possono essere raggiunti da un raggio. Il bit 1 verrà impostato per tutti i pixel che non sono coperti da tutti i raggi.
  • Funzione f viene chiamata per tutte e 4 le direzioni (verticale, orizzontale, entrambe le diagonali). I suoi argomenti specificano il vettore normale della direzione.
  • In funzione f :
    • Viene calcolata la distanza di entrambi i punti di ingresso rispetto alla direzione (d e e) come prodotto punto del punto con il vettore normale passato.
    • Le distanze vengono scambiate se necessario in modo che d sia sempre inferiore o uguale a e.
    • Se la differenza tra d e eè maggiore della larghezza della trave, in questa direzione non sono possibili travi.
    • Altrimenti, passa su tutti i pixel. Impostare il bit 0 se il pixel è raggiungibile da qualsiasi raggio e il bit 1 se non è coperto da tutti i raggi.
  • Contrassegnare i due punti di input con il valore 4. Poiché abbiamo utilizzato i bit 0 e 1 per tenere traccia dello stato, che risulta nei valori da 0 a 3, questo è il valore inutilizzato più piccolo.
  • Passa sopra i pixel be converti i valori nell'intervallo da 0 a 4 nel loro carattere corrispondente mentre li stampi.

puoi probabilmente risparmiare un po 'mettendo l'ultima riga di codice nel incrementatore in quel forciclo
— Non che Charles
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.