Pi naturale # 2 - Fiume


12

Obbiettivo

Dato una stringa con un treno di hash, calcola la sua lunghezza totale e dividi per la distanza dall'inizio alla fine.

Simulazione

Cosa stiamo simulando? Secondo questo articolo , il rapporto tra la lunghezza di un fiume e la distanza tra l'inizio e la fine è di circa Pi! (Questo potrebbe essere stato smentito empiricamente, ma ho potuto trovare i dati e per questa sfida supponiamo che sia vero).

Come lo stiamo simulando?

  • Prendi un input stringa di spazi bianchi e hash
  • Ogni hash ne avrà altri due adiacenti
    • Con l'eccezione del primo e dell'ultimo hash che avrà solo 1
  • Ogni personaggio si trova su un punto reticolare (x, y)
  • x è l'indice del personaggio nella sua riga
    • es. cè il 4 ° carattere in0123c567
  • y è il numero di riga del personaggio
    • ad es. cè sulla terza riga:
      0line
      1line
      2line
      3c...
  • Somma le distanze tra gli hash adiacenti, chiamalo S
  • Prendi la distanza tra il primo e l'ultimo hash, chiamalo D
  • Ritorno S/D

inserisci qui la descrizione dell'immagine

specificazione

  • Ingresso
    • Flessibile, accetta input in uno dei modi standard (es. Parametro di funzione, STDIN) e in qualsiasi formato standard (es. String, Binary)
  • Produzione
    • Flessibile, fornisce output in uno dei modi standard (ad es. Ritorno, stampa)
    • Sono ammessi spazi bianchi, finali e spazi bianchi iniziali
    • Precisione, fornire almeno 4 cifre decimali di precisione (ad es. 3.1416)
  • punteggio
    • Il codice più corto vince!

Casi test

Queste sono le mie approssimazioni dei fiumi. Le mie approssimazioni potrebbero essere povere o queste potrebbero essere un povero campione della popolazione fluviale. Inoltre, ho fatto questi calcoli a mano; Avrei potuto perdere calcolato.

Fiume Giallo

        ### ####           
       #   #    #          
       #       #          #
       #       #         # 
       #       #        #  
      #         #      #   
##   #          # #####    
  ##  #          #         
    ##                     
1.6519

il fiume Nilo

         #     
         #     
          #    
           #   
           #   
          #    
         #     
        #      
        #  #   
        # # #  
         #  #  
            #  
          ##   
         #     
         #     
        #      
        #      
       #       
       #       
       #       
       #       
   #  #        
  # ##         
  #            
  #            
   #           
    #          
     #         
     #         
      #        
     #         
    #          
     #         
      #        
1.5498

fiume Mississipi

 ###            
#   #           
     #          
     #          
    #           
   #            
  #             
  #             
  #             
   #            
    #           
     #          
      #         
       #        
        #       
        #       
        #       
         #      
          #     
           #    
          #     
       ###      
      #         
       #        
      #         
     #          
    #           
    #           
    #           
    #           
     #          
      ##        
        #       
        #       
         ##     
           ##   
             ## 
               #
              # 
             #  
            #   
           #    
          #     
         #      
        #       
        #       
        #       
        #       
        #       
       #        
      #         
     #          
      #         
       #        
        ####    
            #   
             #  
1.5257

TL; DR

Queste sfide sono simulazioni di algoritmi che richiedono solo la natura e il cervello (e forse alcune risorse riutilizzabili) per approssimare Pi. Se hai davvero bisogno di Pi durante l'apocalisse di zombi, questi metodi non sprecano munizioni ! Ci sono nove sfide in totale.


3
Si chiamano hash da soli. "Hashtag" è solo il termine per un tag inline indicato con#<tag>
FlipTack il

1
Suppongo che la distanza dovrebbe essere calcolata usando il teorema di Pitagora. È corretto?
Loovjo,

Inoltre, possiamo prendere l'input come un elenco di righe?
Loovjo,

@Loovjo ^^ Può essere, è la geometria euclidea, quindi comunque vuoi calcolarla va bene. ^ Sì, l'input è flessibile.
NonlinearFruit,

1
@NonlinearFruit Grazie. Quindi è probabile che le versioni ASCII non siano abbastanza sinuose :)
Luis Mendo il

Risposte:


6

MATL , 48 44 42 37 33 byte

Abbastanza pochi byte salvati grazie all'idea di rahnema1 (risposta di Ottava) di far collassare due convoluzioni in una

t5BQ4B&vX^Z+*ssGt3Y6Z+1=*&fdwdYy/

Questo accetta l'input come matrice binaria, con ;come separatore di riga. 1corrisponde all'hash e 0allo spazio.

Provalo online! Oppure verifica tutti i casi di test .

Ecco un convertitore di formato che accetta input come array di caratteri 2D (di nuovo, con ;come separatore) e produce rappresentazioni di stringa delle corrispondenti matrici binarie.

Spiegazione

È stato divertente! Il codice utilizza tre due convoluzioni 2D, ciascuna per uno scopo diverso:

  1. Per rilevare i vicini verticali e orizzontali, che contribuiscono a una distanza di 1, sarebbe la maschera richiesta

    0 1 0
    1 0 1
    0 1 0
    

    Ma vogliamo che ogni coppia di vicini venga rilevata una sola volta. Quindi prendiamo metà della maschera (e l'ultima riga di zeri può essere rimossa):

    0 1 0
    1 0 0
    

    Allo stesso modo, per rilevare i vicini diagonali, che contribuiscono a una distanza sqrt(2), sarebbe la maschera

    1 0 1
    0 0 0
    1 0 1
    

    ma con lo stesso ragionamento di cui sopra diventa

    1 0 1
    0 0 0
    

    Se questa maschera viene moltiplicata per sqrt(2)e aggiunta alla prima, le due convoluzioni possono essere sostituite da una convoluzione con la maschera combinata

    sqrt(2) 1  sqrt(2)
    1       0        0
    
  2. I punti iniziale e finale sono, per definizione, i punti con un solo vicino. Per rilevarli con cui ci comportiamo

    1 1 1
    1 0 1
    1 1 1
    

    e vedere quali punti danno 1come risultato.

Per produrre la maschera combinata dell'articolo 1 è più breve generare il suo quadrato e quindi prendere la radice quadrata. La maschera nell'elemento 2 è un valore letterale predefinito.

t     % Take input matrix implicitly. Duplicate
5B    % 5 in binary: [1 0 1]
Q     % Add 1; [2 1 2]
4B    % 4 in binary: [1 0 0]
&v    % Concatenate vertically
X^    % Square root of each entry
Z+    % 2D convolution, maintaining size
*     % Multiply, to only keep results corresponding to 1 in the input
ss    % Sum of all matrix entries. This gives total distance
Gt    % Push input again. Duplicate
3Y6   % Predefined literal. This gives third mask
Z+    % 2D convolution, maintaining size
1=    % Values different than 1 are set to 0
*     % Multiply, to only keep results corresponding to 1 in the input
&f    % Push array of row indices and array of column indices of nonzeros
d     % Difference. This is the horizontal difference between start and end
wd    % Swap, difference. This is the vertical difference between start and end 
Yy    % Hypothenuse. This gives total distance in straight line
/     % Divide. Display implicitly

2
Alcuni dicevano che la convoluzione è la chiave del successo !
Flawr,

4

Ottava, 99 byte

@(a)sum((c=conv2(a,[s=[q=2^.5 1 q];1 0 1;s],'same').*a)(:))/2/{[x y]=find(c<2&c>0),pdist([x y])}{2}

quasi lo stesso metodo della risposta MATL ma qui è il kernel delle convoluzioni

1.41 ,  1  , 1.41
1    ,  0  , 1 
1.41 ,  1  , 1.41

questo sqrt(2) =1.41è per i vicini diagonali ed 1 è per i vicini diretti, quindi quando sommiamo i valori del risultato sul fiume otteniamo il doppio della distanza reale.
versione non golfata :

a=logical([...
0 0 0 0 0 0 0 0 1 1 1 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 
0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 
0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 
1 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 1 1 1 1 1 0 0 0 0 
0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 
0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]);
sq = sqrt(2);
kernel = [...
    sq ,  1  , sq
    1  ,  0  , 1 
    sq ,  1  , sq];
%2D convolution
c=conv2(a,kernel,'same').*a;
#river length
river_length = sum(c (:))/2;
#find start and end points
[x y]=find(c<2&c>0);
# distance between start and end points
dis = pdist([x y]);
result = river_length/ dis 

Prova (incollalo) su Octave Online


La tua idea di raggruppare le prime due circonvoluzioni in una mi ha salvato alcuni byte :)
Luis Mendo,

{[x y]=find(c<2&c>0),pdist([x y])}{2}è così dannatamente intelligente !!!
Flawr,

una buona notizia è che non abbiamo restrizioni di MATLAB!
rahnema1,

2
@flawr Agreed. Questo dovrebbe andare ai consigli sul golf di Octave !
Luis Mendo il

@LuisMendo alcune voci incluse nei suggerimenti
rahnema1

2

JavaScript (ES6), 178

Input come stringa con newline in forma rettangolare : ogni riga è riempita con spazi della stessa lunghezza (come negli esempi)

r=>r.replace(/#/g,(c,i)=>([d=r.search`
`,-d,++d,-d,++d,-d,1,-1].map((d,j)=>r[i+d]==c&&(--n,s+=j&2?1:Math.SQRT2),n=1),n||(v=w,w=i)),w=s=0)&&s/2/Math.hypot(v%--d-w%d,~(v/d)-~(w/d))

Meno golf

r=>(
  r.replace(/#/g, // exec the following for each '#' in the string
    (c,i) => // c: current char (=#), i: current position
    ( // check in 8 directions
      // note: d starts as the offset to next row, prev x position
      // and is incremented up to offset to next row, succ x position
      // note 2: there are 2 diagonal offsets, then 2 orthogonal offsets
      //         then other 2 diagonal, then 2 more orthogonal
      [d=r.search`\n`,-d, ++d,-d, ++d,-d, 1,-1].map( // for each offset
        (d,j) => // d: current offset, j: array position (0 to 7)
        r[i+d] == c && // if find a '#' at current offset ...
          ( 
            --n, // decrement n to check for 2 neighbors or just 1
            s += j & 2 ? 1 : Math.SQRT2 // add the right distance to s
          ),
      n = 1), // n starts at 1, will be -1 if 2 neighbors found, else 0
      // if n==0 we have found a start or end position, record it in v and w
      n || (v=w, w=i)
   ),
  w=s=0), // init s and w, no need to init v
  // at the end 
  // d is the length of a line + 1
  // s is twice the total length of the river
  // v and w can be used to find the x,y position of start and end
  s/2/Math.hypot(v%--d-w%d,~(v/d)-~(w/d))
)

Test

F=
r=>r.replace(/#/g,(c,i)=>([d=r.search`\n`,-d,++d,-d,++d,-d,1,-1].map((d,j)=>r[i+d]==c&&(--n,s+=j&2?1:Math.SQRT2),n=1),n||(v=w,w=i)),w=s=0)&&s/2/Math.hypot(v%--d-w%d,~(v/d)-~(w/d))

Yellow=`        ### ####           
       #   #    #          
       #       #          #
       #       #         # 
       #       #        #  
      #         #      #   
##   #          # #####    
  ##  #          #         
    ##                     `

Nile=`         #     
         #     
          #    
           #   
           #   
          #    
         #     
        #      
        #  #   
        # # #  
         #  #  
            #  
          ##   
         #     
         #     
        #      
        #      
       #       
       #       
       #       
       #       
   #  #        
  # ##         
  #            
  #            
   #           
    #          
     #         
     #         
      #        
     #         
    #          
     #         
      #        `

Missi=` ###            
#   #           
     #          
     #          
    #           
   #            
  #             
  #             
  #             
   #            
    #           
     #          
      #         
       #        
        #       
        #       
        #       
         #      
          #     
           #    
          #     
       ###      
      #         
       #        
      #         
     #          
    #           
    #           
    #           
    #           
     #          
      ##        
        #       
        #       
         ##     
           ##   
             ## 
               #
              # 
             #  
            #   
           #    
          #     
         #      
        #       
        #       
        #       
        #       
        #       
       #        
      #         
     #          
      #         
       #        
        ####    
            #   
             #  `
console.log('Yellow River',F(Yellow))
console.log('Nile River',F(Nile))
console.log('Mississippi River',F(Missi))

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.