Natural Pi # 2 - Rivière

12

Objectif

Étant donné une chaîne avec un train de hachages, calculez sa longueur totale et divisez par la distance du début à la fin.

Simulation

Que simulons-nous? Selon cet article , le rapport de la longueur d'une rivière à la distance entre le début et la fin est d'environ Pi! (Cela peut avoir été réfuté empiriquement, mais j'ai pu trouver les données et pour ce défi, nous supposerons que c'est vrai).

Comment simulons-nous cela?

  • Prendre une entrée de chaîne d'espaces et de hachages
  • Chaque hachage en aura deux autres adjacents
    • A l'exception du premier et dernier hachage qui n'aura que 1
  • Chaque personnage se trouve sur un point de réseau (x, y)
  • x est l'index du personnage sur sa ligne
    • par exemple cest le 4ème caractère0123c567
  • y est le numéro de ligne du caractère
    • par exemple cest sur la 3ème ligne:
      0line
      1line
      2line
      3c...
  • Additionnez les distances entre les hachages adjacents, appelez-le S
  • Prenez la distance entre le premier et le dernier hachage, appelez-le D
  • Revenir S/D

entrez la description de l'image ici

spécification

  • Contribution
    • Flexible, saisissez les données de n'importe quelle manière standard (par exemple, paramètre de fonction, STDIN) et dans n'importe quel format standard (par exemple chaîne, binaire)
  • Production
    • Flexible, donne une sortie de n'importe quelle manière standard (par exemple retour, impression)
    • Les espaces blancs, les espaces blancs arrière et avant sont acceptables
    • Précision, veuillez fournir au moins 4 décimales de précision (c.-à-d. 3.1416)
  • Notation
    • Le code le plus court gagne!

Cas de test

Ce sont mes approximations des rivières. Mes approximations peuvent être médiocres ou celles-ci peuvent être un échantillon pauvre de la population fluviale. Aussi, j'ai fait ces calculs à la main; J'aurais pu manquer calculé.

Rivière Jaune

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

le Nil

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

Fleuve Mississippi

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

TL; DR

Ces défis sont des simulations d'algorithmes qui ne nécessitent que la nature et votre cerveau (et peut-être quelques ressources réutilisables) pour approximer Pi. Si vous avez vraiment besoin de Pi pendant l'apocalypse zombie, ces méthodes ne gaspillent pas de munitions ! Il y a neuf défis au total.

Non linéaire
la source
3
On les appelle des hachages seuls. "Hashtag" est juste le terme pour une balise en ligne signifiée par#<tag>
FlipTack
1
Je suppose que la distance doit être calculée en utilisant le théorème de Pythagore. Est-ce correct?
Loovjo
Aussi, pouvons-nous prendre l'entrée comme une liste de lignes?
Loovjo
@Loovjo ^^ Cela peut être, c'est la géométrie euclidienne, donc cependant vous voulez le calculer c'est bien. ^ Oui, la saisie est flexible.
NonlinearFruit
1
@NonlinearFruit Merci. Alors c'est probablement que les versions ASCII ne sont pas assez sinueuses :)
Luis Mendo

Réponses:

6

MATL , 48 44 42 37 33 octets

Beaucoup d'octets économisés grâce à l'idée de rahnema1 (réponse Octave) de fusionner deux convolutions en une

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

Cela prend l'entrée comme une matrice binaire, avec ;comme séparateur de lignes. 1correspond au hachage et 0à l'espace.

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Voici un convertisseur de format qui prend les entrées sous forme de tableaux de caractères 2D (encore une fois, avec ;comme séparateur) et produit des représentations de chaînes des matrices binaires correspondantes.

Explication

C'était amusant! Le code utilise trois deux convolutions 2D, chacune dans un but différent:

  1. Pour détecter les voisins verticaux et horizontaux, qui contribuent à une distance de 1, le masque requis serait

    0 1 0
    1 0 1
    0 1 0
    

    Mais nous voulons que chaque paire de voisins soit détectée une seule fois. Nous prenons donc la moitié du masque (et la dernière ligne de zéros peut être supprimée):

    0 1 0
    1 0 0
    

    De même, pour détecter les voisins diagonaux, qui contribuent à une distance de sqrt(2), le masque serait

    1 0 1
    0 0 0
    1 0 1
    

    mais par le même raisonnement que ci-dessus, il devient

    1 0 1
    0 0 0
    

    Si ce masque est multiplié sqrt(2)et ajouté au premier, les deux convolutions peuvent être remplacées par une seule convolution avec le masque combiné

    sqrt(2) 1  sqrt(2)
    1       0        0
    
  2. Les points de départ et d'arrivée sont, par définition, les points avec un seul voisin. Pour les détecter, nous convolons avec

    1 1 1
    1 0 1
    1 1 1
    

    et voir quels points donnent 1comme résultat.

Pour produire le masque combiné de l'élément 1, il est plus court de générer son carré, puis de prendre la racine carrée. Le masque de l'élément 2 est un littéral prédéfini.

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
Luis Mendo
la source
2
Certains disaient que la convolution est la clé du succès !
flawr
4

Octave, 99 octets

@(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}

presque la même méthode que la réponse MATL mais ici le noyau des convolutions est

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

c'est sqrt(2) =1.41pour les voisins diagonaux et 1 pour les voisins directs, donc lorsque nous additionnons les valeurs du résultat sur la rivière, nous obtenons le double de la distance réelle.
version non golfée :

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 

Essayez (collez) sur Octave Online

rahnema1
la source
Votre idée de regrouper les deux premières circonvolutions en une seule m'a fait gagner quelques octets :)
Luis Mendo
{[x y]=find(c<2&c>0),pdist([x y])}{2}est tellement sacrément intelligent !!!
flawr
une bonne nouvelle est que nous n'avons pas de restrictions de MATLAB!
rahnema1
2
@flawr D'accord. Cela devrait aller aux conseils de golf d'Octave !
Luis Mendo
@LuisMendo quelques entrées incluses dans les conseils
rahnema1
2

JavaScript (ES6), 178

Entrée sous forme de chaîne avec des retours à la ligne sous forme rectangulaire : chaque ligne est remplie d'espaces de la même longueur (comme dans les exemples)

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

Moins 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))
)

Tester

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

edc65
la source