Diberi Diagram, Cari X

19

Temukan X

Saya terinspirasi oleh pertanyaan matematika di mana seseorang diminta untuk "Cari X" untuk bentuk yang diberikan. Awalnya, saya hanya akan mendapat tantangan untuk mencetak lokasi x dan y dari karakter 'x' dalam sebuah String. Tapi saya kira itu terlalu sederhana. Jadi saya mempertimbangkan konteks mereka biasanya, dan memutuskan menemukan panjang Garis di sebelah x sepertinya cocok.

Diberikan input string yang berisi Diagram 'garis' ascii serta karakter 'x' tunggal dan berpotensi sampah, cetak panjang satu-satunya garis yang memiliki 'x' yang berbatasan langsung dengannya.

Contohnya

Memasukkan:

|
|
|x
|
|

Ouput:

5

Memasukkan:

|\
| \x
|  \
|___\

Keluaran:

4

Memasukkan:

Diagram of a Wobbly Line:
IRRELEVANTTEXT____
____     ____/
    \___/ X ;)   
      x

Keluaran:

3

Memasukkan:

  ______________
 / ____________ \
 |/ __________ \|
 ||/ ________ \||
 |||/ ______ \|||
 ||||/      \||||
 |||||/  x  |||||
 |||||\_____/||||
 ||||\_______/|||
 |||\_________/||
 ||\___________/|
  \_____________/

Keluaran:

5

Catatan

  • Karakter baris yang valid adalah \/_|
  • \ menghubungkan kiri atas dan kanan bawah itu sendiri.
  • / menghubungkan kanan atas dan kiri bawah itu sendiri.
  • _ menghubungkan kiri dan kanan itu sendiri
  • | menghubungkan bagian atas dan bawah dari dirinya sendiri
  • Garis akan selalu lurus, dan hanya terdiri dari salah satu karakter garis yang diulang n kali.
  • X akan selalu huruf kecil, dan itu akan selalu menjadi satu-satunya dalam diagram.
  • Adjecent mengacu pada x yang persis satu karakter di atas, di bawah, atau di samping.
  • X akan selalu berada di sebelah tepat satu Baris.
  • Tab tidak akan pernah muncul di input.
  • Input dan Output dapat berupa format apa pun yang dapat diterima.
  • Ini Golf Code, jadi Kode Terpendek Menang!
  • SELAMAT BERSENANG-SENANG. LAKUKAN. NIKMATI DIRI.

Implementasi Referensi

ATaco
sumber
Tantangan yang bagus, tapi saya pikir akan lebih baik untuk menjamin tidak ada tab dalam input. Dengan mengatakan itu mungkin terjadi, Anda secara efektif memaksa semua orang untuk menambahkan kode untuk mengonversi tab menjadi 4 ruang, yang tidak ada hubungannya dengan tantangan utama.
Level River St
Ya, Anda punya poin bagus. Saya akan memotong itu.
ATaco
Anda harus menambahkan testcase yang memiliki bentuk yang mirip dengan @jawaban stress-test.
orlp
Tantangan yang sangat cerdas, saya berharap dapat melihat beberapa taktik yang digunakan untuk menyelesaikannya
Darren H

Jawaban:

3

JavaScript (ES6), 165, 155 byte

EDIT: Inline x dan w , untuk menyimpan beberapa byte lagi.

Golf (menganggap input diisi dengan spasi untuk membuat persegi panjang)

t=>([k=e=o=1,v=t.search`\n`+2,-1,-v].some(h=>i=({"|":v-1,"_":1,"/":v,"\\":v})[d=t[r=l=t.search`x`+h]]),[...t].map(_=>o+=(k&=t[l-=i]==d)+(e&=t[r+=i]==d)),o)

Diperluas

/*
   G(<input string,space padded>) => line length
*/
G=t=> {

    /*
     ! Note that these two are inlined, in the "golfed" version !
     "w" - line "width"
     "x" - index of "x"
    */
    x=t.search`x`;
    w=t.search`\n`+1;

    /*
    Locate the "line"    
     l,r - left cursor, right cursor (for navigating along the line)
     k - left stop flag, e - right stop flag
     i - increment
     d - direction (char)
    */
    [k=e=o=1,v=w+1,-1,-w-1].some(h=>i=({"|":w,"_":1,"/":v,"\\":v})[d=t[r=l=x+h]]);

    /* 
     Travel along the line axis in both directions

     Note, the stop condition should rather be: while(k|e), 
     but we iterate over all the chars with map instead (as o is guaranteed to be < # chars),
     to save some space
    */
    [...t].map(_=>o+=(k&=t[l-=i]==d)+(e&=t[r+=i]==d));

    /* 
      Resulting line length
    */
    return o;
};

Uji

G= 
t=>([k=e=o=1,v=t.search`\n`+2,-1,-v].some(h=>i=({"|":v-1,"_":1,"/":v,"\\":v})[d=t[r=l=t.search`x`+h]]),[...t].map(_=>o+=(k&=t[l-=i]==d)+(e&=t[r+=i]==d)),o);

[
G( 
 "| \n" +
 "| \n" +
 "|x\n" +
 "| \n" +
 "| \n"
),

G(
"|\\   \n" +
"| \\x \n" +
"|  \\ \n" +
"|___\\\n"
),

G(
"Diagram of a Wobbly Line:\n" +
"IRRELEVANTTEXT____       \n" +
"____     ____\/           \n" +
"    \___\/ X ;)           \n" +    
"      x                  \n"
),

G(
" ______________ \n"  +
"/ ____________ \\\n" +
"|/ __________ \\|\n" +
"||/ ________ \\||\n" + 
"|||/ ______ \\|||\n" +
"||||/      \\||||\n" +
"|||||/  x  |||||\n"  +
"|||||\_____\/||||\n" +
"||||\_______\/|||\n" +
"|||\_________\/||\n" +
"||\___________\/|\n" +
" \_____________\/\n"
)
]

Contoh hasil (jika Anda menjalankan ini di konsol Alat Pengembang Google Chrome)

[5, 4, 3, 5]

zeppelin
sumber
8

Python 3, 428 408 385 378 byte

Bekerja, tetapi memiliki banyak potensi untuk bermain golf. Saya agak berkarat.

Asumsikan input diisi dengan spasi untuk membuat persegi panjang.

EDIT: Terima kasih kepada @Artyer untuk penghematan 23 byte!

EDIT2: Wow saya benar-benar melewatkan penghematan 6 byte. Disimpan 1 lebih banyak dengan menukar sisi cek yang sama.

*i,=map(list,input().split('\n'))
r=c=s=q=e=w=0
o=lambda y,x:len(i[0])>x>=0<=y<len(i)
d='\/_|'
for l in i:
 if'x'in l:r=i.index(l);c=l.index('x')
for a,b in(1,0),(0,1),(-1,0),(0,-1):
 y,x=r+a,c+b;f=o(y,x)and i[y][x]
 if f in d:s=f;w=d.index(f);q,e=y,x
k=lambda y,x,g=[1,1,0,1][w],v=[1,-1,1,0][w]:o(y,x)and s==i[y][x]and(exec('i[y][x]=0')or 1+k(y+g,x+v)+k(y-g,x-v))
print(k(q,e))

Versi yang diperluas dengan penjelasan:

inputtt='''  ______________.
 / ____________ \
 |/ __________ \|
 ||/ ________ \||
 |||/ ______ \|||
 ||||/      \||||
 |||||/  x  |||||
 |||||\_____/||||
 ||||\_______/|||
 |||\_________/||
 ||\___________/|
  \_____________/'''

# First, we get the input from STDIN and make it
# into a doubly-nested array

*input_text,=map(list,inputtt.split('\n'))

# A pretty cool Python trick to assign 0 to
# mulitple variables at once.

row=col=line_letter=line_row=line_col=line_char_index=0

# A function to check if a certian row and col is
# in bounds or not. Uses python's comparator chaining

in_bounds=lambda y,x:len(input_text[0])>x>=0<=y<len(input_text)

# A string to store all the line characters.
chars='\/_|'

# Search for the x
for line in input_text:

 # If this line contains the x...
 if'x'in line:

     # Mark the row and column
     row=input_text.index(line);col=line.index('x')

# For each direction...
for down,right in(1,0),(0,1),(-1,0),(0,-1):

 # Move in that direction
 y,x=row+down,col+right

 # If the position is in bounds, mark the char at that position
 line_found=in_bounds(y,x)and input_text[y][x]

 # If the char is a line char, set all the variables saying we found it
 if line_found in chars:
  line_letter=line_found
  line_char_index=chars.index(line_found)
  line_row,line_col=y,x

recur=lambda y,x,\
       # Find which directions we are supposed to recur in based on the line char
       g=[1,1,0,1][line_char_index],v=[1,-1,1,0][line_char_index]:\
       # If the char is in bounds and we are still on the line...
       in_bounds(y,x)and input_text[y][x]==line_letter and\
       # Set the spot to a 0, so we won't go back, increment,
       # and recur in both directions
       (exec('i[y][x]=0')or 1+recur(y+g,x+v)+recur(y-g,x-v))

# Finally, print the answer
print(recur(line_row,line_col))
Biru
sumber
Saya telah membuat beberapa saran bermain golf di pastebin.com/zKENQUeR . Jangan ragu untuk menggunakannya jika Anda mau (Total: -18 bytes). Juga, Anda mungkin ingin menambahkan <!-- language-all: lang-py -->untuk penyorotan sintaksis.
Artyer
@Artyer Terima kasih! Aku bodoh karena tidak melakukan sebagian besar dari itu, tetapi aku tidak tahu tentang backslash yang tidak melarikan diri. Saya saat ini sedang menggunakan ponsel, tetapi saya pasti akan memasukkan saran Anda nanti!
Biru
Oh, dan satu lagi: Baris pertama ke *i,=map(list,inputtt.split('\n'))( *i,membuat idaftar alih-alih peta) (-6 byte lebih banyak)
Artyer
Wow ... golf secara keseluruhan.
Erik the Outgolfer
0

Lua, 480 Bytes

Lua, Menjadi Bahasa Verbose, tidak mengalahkan Python Answer. Tapi itu tidak perlu.

a=...s={}for _ in a:gmatch"[^\n]*"do s[#s+1]={}for S in _:gmatch"."do if S=="x"then x=#s[#s]+1y=#s end s[#s][#s[#s]+1]=S end end c="\\/_|"X={-1,1,1,0}Y={-1,-1,0,-1}for _,d in pairs({{x-1,y},{x,y-1},{x+1,y},{x,y+1}})do K=d[2]k=d[1]h=s[K]w=h and h[k]C=w and c:find(w)if C then n=1 j=k J=K while true do j=j+X[C]J=J+Y[C]if s[J]and s[J][j]==w then n=n+1 else break end end j=k J=K while true do j=j-X[C]J=J-Y[C]if s[J]and s[J][j]==w then n=n+1 else break end end print(n)break end end

Mirip dengan implementasi referensi saya, tetapi benar-benar mencoba golf, dan melakukan beberapa hal sedikit lebih pintar dari sebelumnya. Masih mungkin bisa bermain golf sedikit lebih baik.

Dengan komentar.

a=... -- Take the input from the command line.
s={}  -- Store the string as a 2D Table, instead of a multiline string.
for _ in a:gmatch"[^\n]*"do -- For each new row.
    s[#s+1] = {}            -- Make a new sub-table. This is our line.
    for S in _:gmatch"."do  -- For every character.
        if S=="x"then x=#s[#s]+1y=#s end -- If it's an x, mark down the X and Y position of it.
        s[#s][#s[#s]+1]=S                -- Push the character. This could probably be better golfed.
    end
end
c="\\/_|"   -- The ascii line characters.
X={-1,1,1,0}    -- Their X Directionals.
Y={-1,-1,0,-1}  -- Their Y Directionals.
                -- These are inversed to get their opposite direction.
for _,d in pairs({{x-1,y},{x,y-1},{x+1,y},{x,y+1}}) do -- For each up down left and right.
    K=d[2]  -- K = y
    k=d[1]  -- k = x
    h=s[K]  -- h = the yth row
    w=h and h[k]    -- w = the xth character of the yth row, if the yth row exists.
    C=w and c:find(w) -- C = the id of the ascii line character, if w existed.
    if C then
        n=1 -- n = the length of the line.
        j=k -- Temp x
        J=K -- Temp y
        while true do
            j=j+X[C] -- Increment j by the directional of the ascii.
            J=J+Y[C] -- Ditto. for J
            if s[J]and s[J][j]==w then -- if it's still the same.
                n=n+1 -- Add 1 to the length.
            else
                break -- Or stop.
            end
        end
        j=k -- Re-assign the temps as their original.
        J=K
        while true do
            j=j-X[C] -- Search in the other direction.
            J=J-Y[C]
            if s[J]and s[J][j]==w then
                n=n+1
            else
                break
            end
        end
        print(n) -- Print the length.
        break
    end
end
ATaco
sumber
-1

JavaScript (ES6), 175

Asumsikan input diisi dengan spasi untuk membuat persegi panjang.

s=>(o=>{s.replace(/[_|\\/]/g,(c,p)=>[o,-o,1,-1].map(d=>s[p+d]=='x'?[q,k]=[p,c]:c));for(n=z=k>'_'?o:k>'\\'?-1:k>'/'?o-1:o+1;s[q+=z]==k||z<0&&(n=-1,z=-z);)n++})(~s.search`
`)||n

Kurang golf

s=>{
  o = ~s.search`\n`; // offset between rows (negated)
  // look for a line character near an 'x'
  s.replace(/[_|\\/]/g, 
     (c,p)=> // for each line char 'c' in position 'p'
     [o,-o,1,-1].map(d=>s[p+d]=='x' // found a near 'x' ?
                        ?[q,k]=[p,c] // remember char and position
                        :c)
  );
  n=0;
  z=k>'_'?o:k>'\\'?-1:k>'/'?o-1:o+1; // offset to prev char of line
  while (s[q+=z]==k // move to left/top first
         || z<0 && (n=0,z=-z) // at left/top, go back and start counting
        )
    n++;
  return n-1;
}

Uji Titik, bukan spasi untuk kejelasan

f=
s=>(o=>{s.replace(/[_|\\/]/g,(c,p)=>[o,-o,1,-1].map(d=>s[p+d]=='x'?[q,k]=[p,c]:c));for(n=z=k>'_'?o:k>'\\'?-1:k>'/'?o-1:o+1;s[q+=z]==k||z<0&&(n=-1,z=-z);)n++})(~s.search`
`)||n

out=x=>O.textContent+=x

;["|.\n|.\n|x\n|.\n|.\n", "|\\...\n|.\\x.\n|..\\.\n|___\\\n"
,"Diagram of a Wobbly Line:\nIRRELEVANTTEXT...........\n____.....____/...........\n....\\___/.X.;)...........\n......x..................\n"
,"./ ____________ \\\n.|/ __________ \|\n.||/ ________ \\||\n.|||/ ______ \\|||\n.||||/      \\||||\n.|||||/  x  |||||\n.|||||\\_____/||||\n.||||\\_______/|||\n.|||\\_________/||\n.||\\___________/|\n. \\_____________/\n"].forEach(s=>out(s+f(s)+'\n\n'))
<pre id=O></pre>

edc65
sumber