Pi Alam 2 - Sungai


12

Tujuan

Diberikan string dengan kereta hash, hitung panjang totalnya dan bagi dengan jarak dari awal hingga selesai.

Simulasi

Apa yang kita simulasikan? Menurut makalah ini , perbandingan panjang sungai dengan jarak antara awal dan akhir adalah sekitar Pi! (Ini mungkin telah dibantah secara empiris, tetapi saya dapat menemukan data dan untuk tantangan ini kita akan menganggap itu benar).

Bagaimana kita mensimulasikan ini?

  • Ambil input string spasi dan hash
  • Setiap hash akan memiliki dua lainnya yang berdekatan dengannya
    • Dengan pengecualian hash pertama dan terakhir yang hanya memiliki 1
  • Setiap karakter terletak pada titik kisi (x, y)
  • x adalah indeks karakter di barisnya
    • mis. cadalah karakter ke 4 di0123c567
  • y adalah nomor baris karakter
    • misal cada di baris ke-3:
      0line
      1line
      2line
      3c...
  • Jumlah jarak antara hash yang berdekatan, sebut saja S
  • Ambil jarak antara hash pertama dan terakhir, sebut saja D
  • Kembali S/D

masukkan deskripsi gambar di sini

Spesifikasi

  • Memasukkan
    • Fleksibel, ambil input dengan cara standar apa pun (mis. Parameter fungsi, STDIN) dan dalam format standar apa pun (mis. String, Binary)
  • Keluaran
    • Fleksibel, memberikan hasil dengan cara standar apa pun (mis. Mengembalikan, mencetak)
    • Ruang putih, trailing dan ruang putih utama dapat diterima
    • Akurasi, harap berikan setidaknya 4 tempat desimal akurasi (yaitu 3.1416)
  • Mencetak gol
    • Kode terpendek menang!

Uji Kasus

Ini adalah perkiraan saya tentang sungai. Perkiraan saya mungkin buruk atau ini contoh populasi saya yang miskin. Juga, saya melakukan perhitungan ini dengan tangan; Aku bisa saja salah menghitung.

Sungai Kuning

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

sungai Nil

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

Sungai Mississippi

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

TL; DR

Tantangan-tantangan ini adalah simulasi algoritma yang hanya membutuhkan alam dan otak Anda (dan mungkin beberapa sumber daya yang dapat digunakan kembali) untuk memperkirakan Pi. Jika Anda benar-benar membutuhkan Pi selama kiamat zombie, metode ini tidak membuang - buang amunisi ! Ada sembilan tantangan total.


3
Mereka disebut hash sendiri. "Hashtag" hanyalah istilah untuk tag inline yang ditandai dengan#<tag>
FlipTack

1
Saya berasumsi bahwa jarak harus dihitung menggunakan teorema Pythagoras. Apakah ini benar?
Loovjo

Juga, bisakah kita mengambil input sebagai daftar baris?
Loovjo

@Loovjo ^^ Bisa jadi, ini adalah geometri Euclidean jadi bagaimanapun Anda ingin menghitungnya baik-baik saja. ^ Ya, input fleksibel.
NonlinearFruit

1
@NonlinearFruit Terima kasih. Maka mungkin bahwa versi ASCII tidak cukup berliku-liku :)
Luis Mendo

Jawaban:


6

MATL , 48 44 42 37 33 byte

Cukup banyak byte yang disimpan berkat ide rahnema1 (jawaban oktaf) untuk meruntuhkan dua konvolusi menjadi satu

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

Ini mengambil input sebagai matriks biner, dengan ;pemisah baris. 1sesuai dengan hash dan 0ruang.

Cobalah online! Atau verifikasi semua kasus uji .

Berikut ini adalah konverter format yang mengambil input sebagai array char 2D (sekali lagi, dengan ;sebagai pemisah) dan menghasilkan representasi string dari matriks biner yang sesuai.

Penjelasan

Ini sangat menyenangkan! Kode ini menggunakan tiga dua konvolusi 2D, masing-masing untuk tujuan yang berbeda:

  1. Untuk mendeteksi tetangga vertikal dan horizontal, yang berkontribusi jarak 1, masker yang diperlukan adalah

    0 1 0
    1 0 1
    0 1 0
    

    Tetapi kami hanya ingin setiap pasangan tetangga terdeteksi satu kali. Jadi kami mengambil setengah topeng (dan baris nol terakhir dapat dihilangkan):

    0 1 0
    1 0 0
    

    Demikian pula, untuk mendeteksi tetangga diagonal, yang berkontribusi jarak sqrt(2), topeng itu

    1 0 1
    0 0 0
    1 0 1
    

    tetapi dengan alasan yang sama seperti di atas menjadi

    1 0 1
    0 0 0
    

    Jika topeng ini dikalikan dengan sqrt(2)dan ditambahkan ke yang pertama, kedua konvolusi dapat diganti oleh satu konvolusi dengan mask gabungan

    sqrt(2) 1  sqrt(2)
    1       0        0
    
  2. Titik awal dan titik akhir, menurut definisi, adalah titik dengan hanya satu tetangga. Untuk mendeteksi mereka, kami berbelit-belit

    1 1 1
    1 0 1
    1 1 1
    

    dan lihat poin mana yang memberi 1sebagai hasil.

Untuk menghasilkan topeng gabungan dari item 1, lebih pendek untuk menghasilkan kuadrat dan kemudian mengambil akar kuadrat. Topeng dalam item 2 adalah literal yang sudah ditentukan sebelumnya.

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
Beberapa orang sering berkata, konvolusi adalah kunci kesuksesan !
flawr

4

Oktaf, 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}

metode yang hampir sama dengan jawaban MATL tetapi di sini kernel konvolusi

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

itu sqrt(2) =1.41untuk tetangga diagonal dan 1 untuk tetangga langsung sehingga ketika kita menjumlahkan nilai hasil di atas sungai kita mendapatkan dua kali jarak nyata.
versi tanpa ungolfed :

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 

Coba (tempel) di Octave Online


Gagasan Anda untuk menggabungkan dua konvolusi pertama menjadi satu, menyelamatkan saya beberapa byte :)
Luis Mendo

{[x y]=find(c<2&c>0),pdist([x y])}{2}sangat pintar !!!
flawr

kabar baiknya adalah kita tidak memiliki batasan MATLAB!
rahnema1

2
@ flawr Setuju. Itu harus pergi ke tips golf Octave !
Luis Mendo

@LuisMendo beberapa entri termasuk dalam tips
rahnema1

2

JavaScript (ES6), 178

Input sebagai string dengan baris baru dalam bentuk persegi panjang : setiap baris diisi dengan spasi dengan panjang yang sama (seperti pada contoh)

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

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

Uji

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.