pssssssssssssst


31

บทนำ

อันนี้ตรงไปตรงมาทีเดียว เราจะวาดงูใน ascii เกมนี้ได้รับแรงบันดาลใจมาจากเกมงูตัวเก่าที่คุณต้องเก็บผลไม้และเติบโตอย่างต่อเนื่อง

คำนิยาม

กำหนดจำนวนเต็มบวก N ที่แทนความยาวของงูวาดงูเพื่อให้มีร่างกายของ n บวกหัวและหาง

อะไหล่:

  • หัว: <, >, ^, v
  • หาง: @
  • แนวตั้ง: |
  • horizonal: -

มุมทั้งหมดควรมีความพึงพอใจกับ\หรือ/ตามลำดับ เว้นเสียแต่ว่าศีรษะจะปิดที่มุมซึ่งในกรณีนี้หัว<, >, ^, vจะให้ความสำคัญในทิศทางที่งูขดตัว นั่นคือสำหรับความยาว 1 ตัวอย่างมันจะหมุนทวนเข็มนาฬิกาและดังนั้นหัวหันไปทางนั้น >สำหรับการแก้ปัญหาตามเข็มนาฬิกามันจะไปทางขวา

งูจะต้องเริ่มตรงกลางด้วยหาง แต่มันอาจออกไปข้างนอกในทิศทางใดก็ได้ที่คุณเลือกตามเข็มนาฬิกาหรือทวนเข็มนาฬิกา มันจะต้องพันรอบตัวเองอย่างแน่นหนาเมื่อมันขยายออกไปเป็นวงกลม

ตัวอย่าง

/--\
|/\|
||@|
|\-/
\--->

ตำแหน่งที่@เป็นหางและตำแหน่งเริ่มต้น ดังที่เห็นด้านบนหางเริ่มตรงกลางขึ้นไปทางซ้ายในการหมุนทวนเข็มนาฬิกาออกไปด้านนอก

นี่คือความยาว19บวกหางและหัว

เป็นอีกตัวอย่างนี่คือความยาว1:

<\
 @

การชนะ

นี่คือ code-golf ดังนั้นคำตอบที่ถูกส่งมาด้วยจำนวนไบต์ที่น้อยที่สุดจะเป็นผู้ชนะพร้อมกับเวลาที่จะใช้เป็นตัวแบ่งไทเบรก

มีความสุข!


2
@---->มันไม่ได้เป็นอย่างที่ชัดเจนว่าผมไม่ได้เป็นเพียงแค่ได้รับอนุญาตให้วาดงูตรงเช่น คุณอาจต้องการเงื่อนไขที่เข้มงวดมากขึ้นเกี่ยวกับรูปร่างของงู ต้องบอกให้ชัดเจนว่าช่องว่างนั้นอนุญาตหรือไม่
Ton Hospel

1
"งูจะต้องเริ่มตรงกลางด้วยหางของมัน แต่มันอาจออกไปข้างนอกในทิศทางที่คุณเลือกและตามเข็มนาฬิกาหรือทวนเข็มนาฬิกา"
jacksonecac

1
ดังนั้นฉันบอกว่า@เป็นกึ่งกลาง (เป็นไปได้เพิ่มช่องว่างเพื่อให้มัน) ประกาศ "ไปทางขวา" เพื่อเป็นทิศทางและทำให้เพียงหัวชี้ลงและประกาศตามเข็มนาฬิกา คำศัพท์ของคุณอาจดูเหมือนชัดเจนสำหรับคุณ แต่จริงๆแล้วพวกเขาไม่ชัดเจน ฉันรู้ว่าคุณอาจหมายถึงงูขดที่แน่นเท่าที่จะเป็นไปได้ แต่คุณควรทำให้ชัดเจน
Ton Hospel

1
ไม่ต้องกังวล อันนั้นยากกว่ามากเนื่องจากการชดเชยในการท้าทายนั้น
Martin Ender

2
ความท้าทายแรกที่ดี! ยินดีต้อนรับสู่เว็บไซต์!
Luis Mendo

คำตอบ:


10

MATL , 85 83 ไบต์

และฉันคิดว่าการมีspiralbuiltin จะทำให้เป็นรหัสสั้น ๆ ...

Oli2+XH:UQXItH:+XJh(YsXKoQ3I(4J(5l(H:)0HX^XkU(6H(3M1YL3X!P)'|-\/@' '<v>^'KHq))h0hw)

ลองออนไลน์!

คำอธิบาย

ให้Nแทนอินพุต เราจะสร้างเวกเตอร์ที่มีความยาวceil(sqrt(N+2))^2นั่นคือสี่เหลี่ยมจัตุรัสที่เล็กที่สุดซึ่งมีค่าเท่ากับหรือมากกว่าN +2 เวกเตอร์นี้จะเต็มไปด้วยค่าตัวเลขรีดเป็นเกลียว (นั่นคือสาเหตุที่ความยาวของมันต้องเป็นรูปสี่เหลี่ยมจัตุรัสที่สมบูรณ์แบบ) จากนั้นค่าตัวเลขจะถูกแทนที่ด้วยอักขระ

ให้nแทนแต่ละขั้นตอนเริ่มจาก 1 ที่ศูนย์กลางของเกลียว ขั้นตอนที่งูเปลี่ยนให้โดยn 2 +1 (นั่นคือ: 2, 5, 10, ... ) สำหรับ\สัญลักษณ์และn 2 + n +1 (นั่นคือ: 3, 7, 13, ... ) /สำหรับ ขั้นตอนระหว่าง\และ/ควรจะเป็น-และผู้ที่ระหว่าง/และควรจะเป็น\|

เวกเตอร์ถูกสร้างขึ้นเพื่อให้มี1จุดเลี้ยว (2,3,5,7,10,13 ... ) และ0ที่เหลือ เท่าเทียมกันของผลรวมสะสมบอกถ้าแต่ละรายการที่ควรจะเป็นหรือ- |การเพิ่ม 1 ลงในผลลัพธ์นี้เราจะได้เวกเตอร์ที่มี1(สำหรับ|) หรือ2(สำหรับ-) แต่สิ่งนี้ทำให้จุดเปลี่ยนเองกลายเป็น1หรือ2เกินไป ดังนั้นจุดที่เปิดซึ่งมีตำแหน่งที่เรารู้ว่าจะถูกเขียนทับ: ตำแหน่งn 2 +1 จะเต็มไปด้วย3และตำแหน่งn 2 + n +1 4จะเต็มไปด้วย ส่วนท้ายและส่วนหัวเป็นกรณีพิเศษเช่นกันองค์ประกอบแรกของเวกเตอร์ (ส่วนท้าย) ถูกตั้งค่าเป็น5และองค์ประกอบที่มีดัชนีN2 (หัว) 6ตั้ง สุดท้ายองค์ประกอบที่มีดัชนีเกินN 2 0มีการกำหนดให้

นำเข้าN = 19 เป็นตัวอย่างตอนนี้เรามีเวกเตอร์ที่มีความยาว 25:

5 3 4 1 3 2 4 1 1 3 2 2 4 1 1 1 3 2 2 2 6 0 0 0 0

เราจำเป็นต้องหมุนเวกเตอร์นี้เป็นเกลียว สำหรับสิ่งนี้เราใช้ฟังก์ชัน builtin ที่สร้างเมทริกซ์เกลียวตามด้วยการสะท้อนและการขนย้ายเพื่อผลิต:

13 12 11 10 25
14  3  2  9 24
15  4  1  8 23
16  5  6  7 22
17 18 19 20 21 

การทำดัชนีเวกเตอร์ด้วยเมทริกซ์ให้

4 2 2 3 0
1 4 3 1 0
1 1 5 1 0
1 3 2 4 0
3 2 2 2 6

ที่0สอดคล้องกับพื้นที่1สอดคล้องกับ|, 2ไป-, 3ไป\, 4ไป/, 5ไป@และ6ที่ศีรษะ

หากต้องการทราบว่าในสี่ตัวละคร^, <, vหรือ>หัวควรจะมีเราจะใช้ผลรวมสะสมของจุดเลี้ยวที่เราคำนวณไว้ก่อนหน้านี้ โดยเฉพาะค่าที่สองสุดท้ายของผลรวมสะสมนี้ (เช่นค่าN + 1-th) โมดูโล 4 บอกเราว่าควรใช้อักขระใดสำหรับหัว เราจะใช้ค่าที่สองสุดท้ายของผลรวมสะสมไม่ใช่ครั้งสุดท้ายเพราะความต้องการ "ถ้าหัวปลายที่มุมหัว<, >, ^, vจะให้ความสำคัญในทิศทางที่งูม้วน" สำหรับN = 19 >ตัวอย่างหัวเป็น

'|-\/@> 'ตอนนี้เราสามารถสร้างสตริงที่มีตัวอักษรของทุกงูรวมทั้งตัวละครที่เหมาะสมสำหรับหัวในตำแหน่งที่หก: จากนั้นเราจะจัดทำดัชนีสตริงนี้ด้วยเมทริกซ์ด้านบน (การจัดทำดัชนีเป็นแบบ 1 โมดูลและแบบแยกส่วนดังนั้นพื้นที่จะยาวสุด) ซึ่งจะให้

/--\ 
|/\| 
||@| 
|\-/ 
\--->

1
งานที่ยอดเยี่ยม! ขอบคุณสำหรับการเข้าร่วม!
jacksonecac

8

Python 2, 250 233 191 ไบต์

n=input()
l=[''],
a=x=0
b='@'
while a<=n:x+=1;l+=b,;l=zip(*l[::-1]);m=x%2;b='\/'[m]+x/2*'-|'[m];k=len(b);a+=k
l+=b[:n-a]+'>v'[m]+' '*(k-n+a-1),
if m:l=zip(*l[::-1])
for i in l:print''.join(i)
  • บันทึกแล้ว 39 ไบต์ขอบคุณ @JonathanAllan

repl.it

วาดงูโดยหมุนงูทั้งหมด90ºตามเข็มนาฬิกาและเพิ่มส่วนล่างวิธีนี้งูจะเป็นทวนเข็มนาฬิกาเสมอ
เซกเมนต์ใหม่จะเริ่มต้นด้วยเสมอ\และมี-รูปร่างเหมือนด้านข้างและ/ -ด้านคี่ ส่วนขนาด (ไม่มีมุม) เป็น0, 1, 1, 2, 2, 3... floor(side/2)ซึ่งเป็น
หากเซ็กเมนต์สุดท้ายมันจะลบอักขระส่วนเกินเพิ่มส่วนหัวและเติมด้วยช่องว่าง

desired_size=input()
snake=[['']]
snake_size=side=0
new_segment='@'
while snake_size<=desired_size:
    side+=1
    snake+=[new_segment]
    snake=zip(*snake[::-1])
    odd_side=side%2
    new_segment='\/'[odd_side]+side/2*'-|'[odd_side]
    snake_size+=len(new_segment)
diff=desired_size-snake_size
snake+=[new_segment[:diff]+'>v'[odd_side]+' '*(len(new_segment)-diff-1)]
if odd_side:
    snake=zip(*snake[::-1])

for line in snake:print ''.join(line)

งานที่ดี! คุณได้ชัยชนะจาก tiebreaker มาดูกันว่ามีคนอื่นมาด้วยอะไร
jacksonecac

2
แน่นอนว่านี่เป็นภาษาที่เหมาะสำหรับการแก้ปัญหานี้
Neil

+1 ความผิดพลาดเพียงอย่างเดียวคือเมื่อหัวอยู่ในมุมหนึ่งมันหมายถึงการชี้ตรงไม่ใช่รอบมุม
Jonathan Allan

1
บันทึก 16 ไบต์โดยการจัดทำดัชนีเป็นสตริงชอบโดย: '\/'[m], '-|'[m]และ'>v'[m]
โจนาธานอัลลัน

1
ประหยัดอีก 1 โดยการลบช่องว่างระหว่างprintและ''.join
Jonathan Allan

7

JavaScript (ES6), 193 201 203 215 220 224

แก้ไขที่บันทึกไว้ 4 ไบต์ thx @Arnauld
Edit2เปลี่ยนลอจิกไม่เก็บส่วนเพิ่มปัจจุบันสำหรับ x และ y เพียงรับจากทิศทางปัจจุบัน
Edit3มีการบันทึกสองสามไบต์ฉันตัดสินใจที่จะใช้เพื่อการจัดการพื้นที่ว่างที่ดีขึ้น
Edit4 8 ไบต์ที่บันทึกไว้ไม่ได้ทำตามตัวอย่างเกี่ยวกับทิศทางของหัวอย่างแม่นยำเหมือนกับคำตอบอื่น ๆ

เวอร์ชันปัจจุบันใช้งานได้กับ Chrome, Firefox และ MS Edge

คำตอบนี้ให้พื้นที่ต่อท้ายและนำหน้าบางส่วน (และบรรทัดว่าง)

n=>(t=>{for(x=y=-~Math.sqrt(++n)>>1,g=[i=t];(g[y]=g[y]||Array(x).fill` `)[x]='^<v>|-/\\@'[t?n?i-t?4+t%2:x-y?7:6:t%4:8],n--;i=i>1?i-2:++t)d=t&2,t&1?x+=d-1:y+=d-1})(0)||g.map(x=>x.join``).join`
`

ตีกอล์ฟน้อยลงเล็กน้อย

n=>
{
  g = [],
  // to save a few bytes, change line below (adds a lot of spaces)
  // w = ++n,
  w = -~Math.sqrt(++n)
  x = y = w>>1,
  s=c=>(g[y] = g[y] || Array(x).fill(' '))[x] = c, // function to set char in position
  s('@'); // place tail
  for (
     i = t = 0; // t increases at each turn, t%4 is the current direction
     n--;
     i = i > 0 ? i - 2 : t++ // side length increases every 2 turns
  )
     d = t & 2,
     t & 1 ? x += d-1: y += d-1
     s(!n ? '^<v>' [t % 4] // head
          : '|-/\\' [i > 0 ? t % 2 : x-y ? 3 : 2]) // body
  return g.map(x=>x.join``).join`\n`
}

f=
n=>(t=>{for(x=y=-~Math.sqrt(++n)>>1,g=[i=t];(g[y]=g[y]||Array(x).fill` `)[x]='^<v>|-/\\@'[t?n?i-t?4+t%2:x-y?7:6:t%4:8],n--;i=i>1?i-2:++t)d=t&2,t&1?x+=d-1:y+=d-1})(0)||g.map(x=>x.join``).join`
`

function update() {
  O.textContent=f(+I.value);
}

update()
<input type=number id=I value=19 oninput='update()' 
 onkeyup='update() /* stupid MS browser, no oninput for up/down keys */'>
<pre id=O>


คุณสามารถบันทึกไม่กี่ไบต์โดยแทนที่(' ')ด้วย` ` และ('@')ด้วย`@`
Arnauld

@Arnauld Array (2) .fill` `==> [ Array[1], Array[1] ]ในขณะที่Array(2).fill(' ')==>[' ',' ']
usandfriends

@usandfriends - จริง แต่นั่นไม่ควรสร้างความแตกต่างเมื่อเข้าร่วม
Arnauld

@Arnauld ตอนแรกฉันเห็นด้วยกับเราและเพื่อน แต่มันใช้งานได้จริง ขอบคุณ
edc65

@TravisJ มันไม่ทำงานใน Chrome แต่ดูเหมือนว่า Firefox จะทำงาน
Adnan

3

JavaScript (ES7), 200 ไบต์

(n,s=(n*4+1)**.5|0,i=+`1201`[s%4],d=i=>`-`.repeat(i))=>[...Array(s-2>>2)].reduce(s=>`/-${d(i)}\\
${s.replace(/^|$/gm,`|`)}
|\\${d(i,i+=2)}/`,[`/\\
|@`,`/-\\
|@/`,`@`,`/@`][s%4])+`
\\${d(n-(s*s>>2))}>`

รุ่น ES6 เพื่อความสะดวกในการทดสอบ:

f=(n,s=Math.sqrt((n*4+1))|0,i=+`1201`[s%4],d=i=>`-`.repeat(i))=>[...Array(s-2>>2)].reduce(s=>`/-${d(i)}\\
${s.replace(/^|$/gm,`|`)}
|\\${d(i,i+=2)}/`,[`/\\
|@`,`/-\\
|@/`,`@`,`/@`][s%4])+`
\\${d(n-(s*s>>2))}>`;
<input type=number min=1 oninput=o.textContent=f(this.value)><pre id=o>


การใช้งานที่น่าสนใจ ฉันไม่ได้คิดที่จะทำเช่นนั้น ขอบคุณสำหรับการมีส่วนร่วมและเป็นงานที่ดี !!
jacksonecac

3

Perl, 111 110 ไบต์

รวม +1 สำหรับ -p

กำหนดขนาดให้กับ STDIN

snake.pl:

#!/usr/bin/perl -p
s%> %->%+s%\^ %/>%||s/
/  
/g+s%.%!s/.$//mg<//&&join"",//g,$/%seg+s/ /^/+y%/\\|>-%\\/\-|%for($\="/
\@
")x$_}{

! น่ากลัว งานที่ดี! ขอบคุณสำหรับการมีส่วนร่วม!
jacksonecac

0

รุ่นที่ 563 ไบต์

@echo off
if %1==1 echo /@&echo v&exit/b
set w=1
:l
set/ah=w,a=w*w+w
if %a% gtr %1 goto g
set/aw+=1,a=w*w
if %a% leq %1 goto l
:g
call:d
set r=/%r%\
set/ae=h%%2,w=%1-h*w+2
for /l %%i in (1,1,%h%)do call:r
call:d
echo \%r%^>
exit/b
:d
set r=
for /l %%i in (3,1,%w%)do call set r=%%r%%-
exit/b
:r
echo %r:!=^|%
if %e%==0 set r=%r:@!=\/%
set r=%r:@/=\/%
set r=%r:!\=\-%
set r=%r:/@=\/%
set r=%r:/!=-/%
set r=%r:@!=\/%
set r=%r:/\=!@%
set r=%r:/-=!/%
if %e%==1 set r=%r:/\=@!%
set r=%r:/\=@/%
set r=%r:-\=\!%
if %e%==1 set r=%r:/\=/@%

คำอธิบาย: กรณีพิเศษ 1 เนื่องจากโค้ดที่เหลือต้องใช้ความกว้างของงูอย่างน้อยสองตัว จากนั้นคำนวณสี่เหลี่ยมจตุรัสที่ใหญ่ที่สุด (ไม่ว่าจะเป็นสี่เหลี่ยมจัตุรัสที่แน่นอนหรือสี่เหลี่ยมจัตุรัสกว้างกว่าที่สูง 1) ซึ่งพื้นที่นั้นจะน้อยกว่าความยาวของงู งูจะขดตัวในสี่เหลี่ยมนี้เริ่มต้นที่มุมซ้ายล่างและลงท้ายด้วยหางที่อยู่ตรงกลางและความยาวที่เหลือจะวิ่งอยู่ใต้ก้นสี่เหลี่ยม สี่เหลี่ยมถูกสร้างขึ้นจากการแทนที่สตริงแบบง่าย เวลาส่วนใหญ่ในแต่ละบรรทัดนั้นถูกสร้างขึ้นจากบรรทัดก่อนหน้าโดยการย้ายเส้นทแยงมุม 1 ขั้น แต่เห็นได้ชัดว่าหางจะต้องได้รับการจัดการ


! น่ากลัว ขอบคุณสำหรับการมีส่วนร่วม!
jacksonecac

-1

Python 2.7 หน่วย 1230 ไบต์

ฉันยังใหม่กับ python และ code golf แต่ฉันรู้สึกว่าฉันต้องตอบคำถามของฉันเอง แม้ว่ามันจะสนุกมากก็ตาม!

def s(n):
x = []
l = 0
if n % 2 == 1:
    l = n
else:
    l = n + 1
if l < 3:
    l = 3
y = []
matrix = [[' ' for x in range(l)] for y in range(l)] 
slash = '\\'
newx = l/2
newy = l/2
matrix[l/2][l/2] = '@'
newx = newx-1
matrix[newx][newy] = slash
#newx = newx-1
dir = 'West'

for i in range(0, n-1):    
    newx = xloc(newx, dir)
    newy = yloc(newy, dir)
    sdir = dir
    dir = cd(matrix, newx, newy, dir)
    edir = dir

    if (sdir == 'West' or sdir == 'East') and sdir != edir:
        matrix[newx][newy] = '/'
    else:
        if (sdir == 'North' or sdir == 'South') and sdir != edir:
            matrix[newx][newy] = '\\'
        else:
            if dir == 'East' or dir == 'West':
                matrix[newx][newy] = '-'
            else:
                matrix[newx][newy] = '|'
newx = xloc(newx, dir)
newy = yloc(newy, dir)
sdir = dir
dir = cd(matrix, newx, newy, dir)
edir = dir
print 'eDir: ' + dir
if dir == 'North':
    matrix[newx][newy] = '^'
if dir == 'South':
     matrix[newx][newy] = 'v'
if dir == 'East':
     matrix[newx][newy] = '>'
if dir == 'West':
     matrix[newx][newy] = '<'    


p(matrix, l)

def cd(matrix, x, y, dir):    
if dir == 'North':
    if matrix[x][y-1] == ' ':
        return 'West'
if dir == 'West':
    if matrix[x+1][y] == ' ':
        return 'South'
if dir == 'South':
    if matrix[x][y+1] == ' ':    
        return 'East'
if dir == 'East':
    if matrix[x-1][y] == ' ':        
        return 'North'
return dir

def p(a, n):
for i in range(0, n):
    for k in range(0, n):
        print a[i][k],
    print ' '

def xloc(x, dir):
if dir == 'North':
    return x -1
if dir == 'West':
    return x
if dir == 'East':
    return x 
if dir == 'South':
    return x + 1
 def yloc(y, dir):
if dir == 'North':
    return y
if dir == 'West':
    return y - 1
if dir == 'East':
    return y + 1
if dir == 'South':
    return y

s(25)

https://repl.it/Dpoy


5
นี้สามารถลดลงอย่างมากเพียงแค่ลบช่องว่างที่ไม่จำเป็นขึ้นบรรทัดใหม่ความคิดเห็นฟังก์ชั่นและอื่น ๆ
Addison Crump
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.