Island Golf # 1: Circumnavigation


43

นี่เป็นครั้งแรกในชุดของความท้าทายของ Island Golf ความท้าทายต่อไป

ได้รับเกาะในรูปแบบ ASCII เอาท์พุทเส้นทางที่เหมาะสมที่สุดเพื่อแล่นเรือรอบเกาะ

อินพุต

ข้อมูลที่คุณป้อนจะเป็นตารางสี่เหลี่ยมที่ประกอบด้วยอักขระสองตัวซึ่งแสดงถึงที่ดินและน้ำ ในตัวอย่างด้านล่างที่ดิน#และน้ำเป็น.แต่คุณอาจแทนที่อักขระสองตัวที่คุณต้องการ

...........
...##......
..#####....
..#######..
.#########.
...#######.
...#####.#.
....####...
...........

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

....
.#..
..#.
....

เอาท์พุต

รหัสของคุณจะต้องส่งออกกริดเดียวกันโดยมีcircumnavigation ที่สั้นที่สุดเอาไว้ ในตัวอย่างด้านล่างเส้นทาง circumnavigation จะถูกวาดด้วยoแต่คุณสามารถทดแทนอักขระใดก็ได้ตราบใดที่มันแตกต่างจากตัวอักษรพื้นดินและน้ำ

circumnavigationเป็นโค้งปิดง่ายวาดทั้งหมดบนกระเบื้องน้ำที่ล้อมรอบอย่างเต็มที่กระเบื้องแผ่นดินทั้งหมดบนตาราง การเชื่อมต่อในแนวทแยงจะได้รับอนุญาต ตัวอย่างเช่นนี่คือ circumnavigation ของเกาะด้านบน (แต่ไม่ใช่อันที่สั้นที่สุด):

.ooooo.....
o..##.oo...
o.#####.o..
o.#######o.
o#########o
ooo#######o
..o#####.#o
..oo####..o
....oooooo.

ความยาวของ circumnavigation ถูกคำนวณดังนี้: สำหรับทุกคู่ของไพ่ที่ติดกันบนเส้นทางถ้าพวกเขาเชื่อมต่อในแนวนอนหรือแนวตั้งเพิ่ม 1; หากพวกเขาเชื่อมต่อในแนวทแยงมุมเพิ่ม√2 ความยาวของเส้นทางด้านบนคือ 22 + 7√2 (≈ 31.9)

สั้นที่สุด circumnavigation เป็น circumnavigation กับระยะเวลาที่สั้นที่สุด โปรแกรมของคุณควรออกเส้นทางใดเส้นทางหนึ่งที่ตรงตามเงื่อนไขนี้ สำหรับเกาะส่วนใหญ่จะมีวิธีแก้ไขที่เป็นไปได้หลายอย่าง นี่คือทางออกหนึ่งสำหรับเกาะด้านบนที่มีความยาว 10 + 13√2 (≈ 28.4):

...oo......
..o##oo....
.o#####oo..
.o#######o.
o#########o
.o.#######o
..o#####.#o
...o####.o.
....ooooo..

รายละเอียด

วิธีการแก้ปัญหาของคุณอาจจะเป็นโปรแกรมเต็มรูปแบบหรือฟังก์ชั่น วิธีการอินพุตและเอาต์พุตดีฟอลต์ใด ๆนั้นเป็นที่ยอมรับ

อินพุตและเอาต์พุตของคุณอาจเป็นสตริงหลายบรรทัดหรือรายการสตริง หากภาษาของคุณมีประเภทอักขระที่แตกต่างจากสตริงอักขระเดี่ยวคุณอาจแทนที่ "รายการอักขระ" สำหรับ "สตริง" ในประโยคก่อนหน้า หากภาษาของคุณจำเป็นต้องใส่ความสูงและ / หรือความกว้างของตารางคุณสามารถทำได้ เอาต์พุตของคุณอาจ (เป็นทางเลือก) มีบรรทัดใหม่ต่อท้ายหนึ่งบรรทัด ดังที่ได้กล่าวไว้ข้างต้นคุณสามารถใช้อักขระที่แตกต่างกันสามตัวแทน#.o(โปรดระบุในการส่งอักขระที่คุณใช้)

กรณีทดสอบ

A.หมู่เกาะที่มี circumnavigations สั้นที่สุดที่ไม่ซ้ำกัน:

...
.#.
...

.o.
o#o
.o.

......
.####.
......

.oooo.
o####o
.oooo.

......
......
..##..
...#..
......
......

......
..oo..
.o##o.
..o#o.
...o..
......

.......
.#####.
...#...
...#...
.#####.
.......

.ooooo.
o#####o
o..#..o
o..#..o
o#####o
.ooooo.

.......
...#...
...#...
.#####.
...#...
...#...
.......

...o...
..o#o..
.o.#.o.
o#####o
.o.#.o.
..o#o..
...o...

.......
.#####.
.##..#.
..#..#.
.......

.ooooo.
o#####o
o##..#o
.o#..#o
..oooo.

B.ตัวอย่างเกาะที่มีทางออกที่เป็นไปได้หลายประการ:

........
....##..
...####.
..###...
.#####..
.#####..
..##....
........

ผลลัพธ์ที่เป็นไปได้:

....oo..
...o##o.
..o####o
.o###.o.
o#####o.
o#####o.
.o##oo..
..oo....

....oo..
...o##o.
..o####o
.o###.o.
o#####o.
o#####o.
.o##.o..
..ooo...

....oo..
...o##o.
..o####o
.o###..o
o#####.o
o#####o.
.o##oo..
..oo....

....oo..
...o##o.
..o####o
.o###..o
o#####.o
o#####o.
.o##.o..
..ooo...

C. กรณีทดสอบขนาดใหญ่เป็นส่วนสำคัญ


นี่คือ : รหัสที่สั้นที่สุดในแต่ละภาษาชนะ


1
การวนรอบสั้นที่สุดสำหรับกรณีทดสอบครั้งที่ 3 คือรูปแบบ 'ก้อน' ในเกมแห่งชีวิตของ Conway!
สหาย SparklePony

คำตอบ:


18

Mathematica (รุ่น 9), 165 ไบต์

ConvexHullMeshฟังก์ชั่นสั้น ๆที่ดีที่ Greg Martin ใช้นั้นถูกนำมาใช้ใน Mathematica เวอร์ชั่น 10 เท่านั้นดังนั้นฉันคิดว่าฉันจะพยายามโดยไม่ใช้มันด้วยการใช้ Mathematica รุ่นที่ 9 โบราณของฉันฉันพยายามทำให้มันสั้นลงเล็กน้อย! มันเป็นฟังก์ชั่นที่ใช้เวลาและการกลับรายการของสตริง (มี., #และoเป็นสัญลักษณ์)

""<>#&/@("o"MorphologicalTransform[MorphologicalComponents[#,Method->"ConvexHull"],Max[#(1-#[[2,2]])CrossMatrix@1]&]+"#"#/.{0->"."})&[Characters@#/.{"."->0,"#"->1}]&

คำอธิบาย:

  • ขั้นแรกให้Characters@# /. {"."->0, "#"->1}เปลี่ยนอินพุตเป็นเมทริกซ์ของ0s และ1s
  • "o"MorphologicalTransform[MorphologicalComponents[#,Method->"ConvexHull"],Max[#(1-#[[2,2]])CrossMatrix@1]&]+"#"#แล้วใช้ที่มีประสิทธิภาพ ( แต่มากไบต์หนัก ... ) ภาพ Mathematica ความสามารถในการประมวลผลเพื่อเติมครั้งแรกในเกาะเปลือกนูน (ซึ่งเป็นรูปร่างที่คุณต้องการได้หากคุณยืดชิ้นส่วนของสตริงรอบ) และจากนั้นนำเขตแดน จากนั้นเราคูณเมทริกซ์นี้ด้วยสตริง"o"เพื่อรับเมทริกซ์ของ0s และ"o"s (ขอบคุณความสามารถในการปรับตัวที่น่าประทับใจของ Mathematica) และเพิ่มสิ่งนี้กับ"#"เมทริกซ์ของเกาะ
  • ในที่สุด""<>#& /@ (... /. {0->"."})เปลี่ยนเมทริกซ์ของ"o"s, "#"s และ0s นี้เป็นเมทริกซ์ของ"o"s, "#"s และ"."s และรวมแต่ละแถวเป็นสตริง

เมื่อเราทดสอบในตัวอย่างBเราจะได้ผลลัพธ์

{"....oo..",
 "...o##o.",
 "..o####o",
 ".o###..o",
 "o#####o.",
 "o#####o.",
 ".o##oo..",
 "..oo...."}

[แก้ไขขอบคุณ Greg Martin:] หากเราได้รับอนุญาตให้ใช้อาร์เรย์ของตัวละครแทนที่จะเป็นรายการของสตริงเราสามารถตัดส่วนนี้ให้เหลือ 144 ไบต์:

"o"MorphologicalTransform[MorphologicalComponents[#,Method->"ConvexHull"],Max[#(1-#[[2,2]])CrossMatrix@1]&]+"#"#/.{0->"."}&[#/.{"."->0,"#"->1}]&

1
ทำได้ดีมาก! ฉันไม่เคยรู้เกี่ยวกับMorphologicalComponents[#, Method->"ConvexHull"] :) คุณสามารถบันทึกไบต์ได้มากขึ้นโดยสมมติว่าอินพุตถูกแบ่งออกเป็นตัวละครอยู่แล้ว
Greg Martin

@ GregMartin ฉันไม่รู้เกี่ยวกับการใช้MorphologicalComponentsอย่างใดอย่างหนึ่งจนถึงวันนี้!
ไม่ใช่ต้นไม้

Mathematica ฝึกหัดที่นี่: ฉันจะเรียกฟังก์ชันนี้ได้อย่างไร ฉันลองf[{"...",".#.","..."}]และพบข้อผิดพลาด
DLosc

@DLosc, fฟังก์ชั่นเป็นสิ่งที่ทั้งไม่ได้เป็นเพียง (พูดอย่างเคร่งครัดมันคือสิ่งที่อยู่หลังเครื่องหมายอัฒภาค) ในการเรียกใช้ฟังก์ชันพิมพ์สิ่งทั้งหมดลงในหน้าต่าง Mathematica ตามด้วย[ข้อมูลที่คุณป้อนและ]ดังนั้นจึงควรมีลักษณะคล้ายกันf@m_:=m(1-m[[2,2]]) . . . #/.{"."->0,"#"->1}]&[{"...", ".#.", "..."}](ย่อสำหรับพื้นที่)
ไม่ใช่ต้นไม้

@DLosc ดีนั่นเป็นเพราะรหัสเสีย ฉันคิดว่าฉันคงตอนนี้แล้ว! (ฉันไม่รู้ว่าเกิดอะไรขึ้นที่นั่นขอโทษ…)
ไม่ใช่ต้นไม้

11

(แต่แก้ปัญหาการโหวตของ Notatreeดีกว่า!)

Mathematica, 168 ไบต์

(x_~n~y_:=Min[Norm[x-#]&/@y];i=#;p=i~Position~#&;t=p["#"|"."]~Select~#&;(i~Part~##="o")&@@@t[#~n~t[ConvexHullMesh[Join[s=p@"#",#+{.1,.1}&/@s]]~RegionMember~#&]==1&];i)&

ฟังก์ชั่นที่บริสุทธิ์รับอาร์เรย์ของตัวละคร 2D เป็นอินพุตและส่งกลับอาร์เรย์ของตัวละคร 2D รุ่นที่อ่านง่ายกว่า:

1  (x_~n~y_ := Min[Norm[x - #] & /@ y];
2  i = #; p = i~Position~# &; 
3  t = p["#" | "."]~Select~# &;
4  (i~Part~## = "o") & @@@ 
5    t[#~n~
6      t[ConvexHullMesh[
7        Join[s = p@"#", # + {.1, .1} & /@ s]]
8      ~RegionMember~# &] == 1 &];
9  i) &

บรรทัดที่ 1 กำหนดฟังก์ชั่นnที่สร้างระยะทาง (เล็กที่สุด) ระหว่างจุดxในระนาบและชุดyของจุดอื่น บรรทัดที่ 2 กำหนดค่าเริ่มต้นให้กับตัวแปรiทั้งสองเพื่อแก้ไขความกำกวมในการแก้ปัญหาในภายหลังและเพื่อให้สามารถแก้ไขได้เพื่อสร้างผลลัพธ์ในที่สุด บรรทัดที่ 2 นอกจากนี้ยังกำหนดฟังก์ชั่นที่ส่งกลับพิกัดของเหตุการณ์ทั้งหมดของการป้อนข้อมูลในpi

ในบรรทัดที่ 3 p["#" | "."]หมายถึงทุกพิกัดเดียวจากแผนที่อินพุต (เนื่องจากอักขระทั้งหมดเป็น"#"หรือ".") ดังนั้นจึงtเป็นฟังก์ชั่นที่เลือกเฉพาะพิกัดที่ตรงตามคุณสมบัติที่ยังไม่ได้ระบุ On line ที่ 4 i~Part~## = "o"จะเปลี่ยนพวงของรายการของiตัวละคร"o"; ตัวละครเหล่านั้นจะถูกเลือกจากชุดพิกัดที่เป็นไปได้ตามเนื้อหาในบรรทัดที่ 5-8 และบรรทัดที่ 9 จะส่งคืนคำตอบเมื่อคำนวณ

เอาล่ะโครงสร้างพื้นฐานเสร็จแล้วตอนนี้ถึงการคำนวณจริง ConvexHullMeshเป็น Mathematica ในตัวสำหรับการคำนวณฮัลล์นูนของชุดของจุด (รูปหลายเหลี่ยมนูนที่เล็กที่สุดที่มีคะแนนเหล่านั้น) การพูดอย่างมีศีลธรรมนี่ควร "เติม" อ่าวและฟยอร์ดของเกาะ (ซึ่งก็คือs = p@"#") เพื่อควบคุมพวกเขาออกจาก cicrumnavigation ของเรา มีปัญหาเล็กน้อยConvexHullMeshเมื่อชุดคะแนนนั้นอยู่ในบรรทัด (ขอบคุณกรณีทดสอบ # 2) ซึ่งเราแก้ไขได้ด้วยการผนวกเวอร์ชันออฟเซ็ตเล็กน้อยของsตัวเองในบรรทัดที่ 7 เอาต์พุตนี้เป็นรูปหลายเหลี่ยมดังนั้นบรรทัด 7 -9 (t[...~RegionMember~# &]) สร้างรายการของจุดที่มีพิกัดจำนวนเต็มในรูปหลายเหลี่ยมนั้น ในที่สุดบรรทัดที่ 5 และจุดสิ้นสุดของบรรทัดที่ 9 จะคำนวณคะแนนทั้งหมดที่อยู่ในระยะที่แน่นอน 1 (ไม่ใช่ 0) จากชุดจำนวนเต็มนี้ ชุดนั้นจะกลายเป็นเส้นทาง circumnavigating

ด้านล่างคือผลลัพธ์สำหรับกรณีทดสอบขนาดใหญ่ที่ลิงค์ของ OP สังเกตุที่มุมบนซ้ายตัวเลือกที่ผิดปกติของเวลาที่จะไปทางตะวันตกเทียบกับทิศตะวันตกเฉียงใต้บอกใบ้ถึงความจริงที่ว่ามันเป็นเงาของเส้นลาดที่มองไม่เห็น -2/3 ระหว่างคาบสมุทรสองเส้น

........................
.............o..........
...........oo#ooooooo...
..........o#.#.##...#o..
........oo.#.#.###.##o..
.......o..########.##o..
.....oo...############o.
...oo#....############o.
..o#.###.##############o
.o##.##################o
.o####################o.
.o.##################.o.
.o##################..o.
.o..################..o.
o###################..o.
o#####################o.
o.##################.o..
o####################o..
o#...##############.o...
o##...#############o....
o#.....###....#oooo.....
.oooooo#ooooooo.........
.......o................

Mathematica มักแสดงถึงสตริงว่าเป็น 1D arrays ของตัวละครหรือไม่? ถ้าไม่เช่นนั้นคุณจะต้องรับ / คืนอาเรย์ของสตริง 1D แทน (และหวังว่าจะได้คำอธิบาย! ฉันไม่คิดว่าฉันจะสามารถเรียกใช้สิ่งนี้ได้โดยไม่ต้องใช้ Mathematica ใช่ไหม?)
DLosc

Mathematica มีประเภทข้อมูลสตริง แต่ดูเหมือนว่าอาร์เรย์ของตัวละครยังใช้ได้กับวัตถุประสงค์ของเว็บไซต์นี้ (เช่นฉันได้เรียนรู้สิ่งนี้เมื่อฉันเริ่มใช้ PPCG แต่ฉันลืมข้อกฎหมายว่าทำไม) ใช่น่าเสียดายที่ Mathematica นั้นเป็นแบบไม่เสียค่าใช้จ่ายและทำให้หลายคนไม่สามารถเข้าถึงได้ :(
Greg Martin

1
@GregMartin ฉันมักจะพยายามออกโซลูชั่น Mathematica ที่sandbox.open.wolframcloud.com
OVS

ฉันทามติปัจจุบันบอกว่าไม่สามารถใช้รายการสตริงอักขระเดี่ยวแทนสตริง เท่าที่ฉันสามารถบอกได้ว่า "ตัวละคร" ใน Mathematica เป็นเพียงสายอักขระตัวเดียวเช่นใน Python สถานการณ์แตกต่างกันในภาษาเช่น Java ซึ่งมีcharประเภทแยกต่างหาก ในกรณีนั้นcharสามารถใช้อาเรย์แทนสตริงได้
DLosc

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

10

Python 3, 779 ไบต์ (เยื้องกับแท็บ)

นี่คือโปรแกรมทั้งหมด มันอ่านอินพุตจาก stdin และพิมพ์ไปยัง stdout Stdin ต้องลงท้ายด้วย EOF ตัวอย่างการรันด้วยอินพุตขนาดใหญ่: https://ideone.com/XIfYY0

import itertools,sys
L=list
C=itertools.count
d=L(map(L,filter(None,sys.stdin.read().split('\n'))))
X=len(d[0])
Y=len(d)
R=range
def P(r):return all(d[y][x]=='.'for x,y in r)
def S(f):
    for n in C(0):
        if P(f(n)):l=n
        else:break
    for n in C(l+1):
        if P(f(n)):return l,n
def f(V,a,*b):return L(eval('lambda '+a+':('+i+')',V)for i in b)
V=locals()
def D(n):
    y=min(n,Y-1);x=n-y
    while y>=0and x<X:yield(x,y);x+=1;y-=1
def E(n):
    x=max(0,n-Y);y=x+Y-n
    while y<Y and x<X:yield(x,y);x+=1;y+=1
F=f(V,'p','(p,y)for y in R(0,Y)','(x,p)for x in R(0,X)')+[D,E]
r=f(V,'x,y','x','y','x+y','x-y+Y')
B=L(map(S,F))
for x in R(0,X):
    for y in R(0,Y):
        z=L(zip(r,B))
        if all(g(x,y)in R(a,b+1)for g,(a,b)in z)and any(g(x,y)in e for g,e in z):d[y][x]='o'
print('\n'.join(''.join(x)for x in d))

แนวคิดนี้ง่ายมาก: มันคำนวณขอบเขตแปดเหลี่ยมที่เล็กที่สุดและดึงเซลล์ที่อยู่ภายในขอบเขตที่คำนวณได้ทั้งหมดและตัดกันอย่างน้อยหนึ่งขอบ


1
คุณไม่จำเป็นต้องใช้sys.stdinเป็นอินพุต input()รับ multiline จะทำงานและค่าใช้จ่ายน้อยกว่าไบต์
Dead Possum

2
อาจสามารถแทนที่R(0,x)ด้วยR(x)
ceilingcat

+1 สำหรับไม่ได้ใช้งานในตัว
Robert Fraser

1
ดี! เคล็ดลับการเล่นกอล์ฟเพิ่มเติม: บันทึก 5 ไบต์แต่ละโดยใช้ lambdas เพื่อกำหนดPและf; L(generator expression)=> [generator expression]; F, rและBดูเหมือนว่าจะใช้เพียงครั้งเดียวเท่านั้นและจะสามารถ inlined
DLosc

8

JavaScript (ES6), 369 343 ไบต์

f=s=>(a=s.split`
`.map(s=>[...s]),m=Array(8),a.map((b,i)=>b.map((c,j)=>c>'#'||[i-j,i,j+i,j,j-i,-i,-i-j,-j].map((d,k)=>d>m[k]||(m[k]=d-1)))),[o,p,q,r,t,u,v,w]=m,g=(i,j,k,l,...p)=>i-k|j-l?a[i][j]=g(i+(k>i)-(k<i),j+(l>j)-(l<j),k,l,...p):1/p[0]?g(k,l,...p):'o',g(p,p-o,p,q-p,q-r,r,r-t,r,-u,t-u,-u,u-v,w-v,-w,o-w,-w,p,p-o),a.map(b=>b.join``).join`
`)

คำอธิบาย: สตริงถูกแบ่งออกเป็นอาร์เรย์อักขระ (ฉันไม่ชัดเจนว่าการป้อนข้อมูลอาร์เรย์อักขระนั้นยอมรับได้หรือไม่) อาร์เรย์จะวนซ้ำแล้วและตำแหน่งของสี่เหลี่ยมที่ดินทั้งหมดตั้งอยู่ เส้นขอบเขตที่กำหนดโดยสมการx - y = o, x = p, x + y = q, y = r, y - x = t, -x = u, -x - y = v, -y = wมีความมุ่งมั่นดังกล่าวว่าพารามิเตอร์เป็นไปได้สูงสุดคือเลือกที่ที่ดินทั้งหมดโกหกเกินเส้น นี่เป็นผลของการล้อมเกาะในรูปแปดเหลี่ยม พิกัดของมุมของรูปแปดเหลี่ยมจะถูกคำนวณอย่างง่ายดายจากพารามิเตอร์และเติมเซลล์บนขอบของมันแล้วอาร์เรย์จะถูกรวมเข้าด้วยกันกลับเข้าไปในสตริง เหตุผลพอเพียงแปดเหลี่ยมมีดังนี้:

   /o#     /o#     /o#
 |/o #   |/o #   |/ o#
 *o###   * o #   *  o#
/|o #   /|o #   /| o#
 |o#     |o#     |o#

พิจารณามุมของรูปแปดเหลี่ยม ในบางจุดตามขอบทั้งสองเส้นทางจะถูก จำกัด โดยที่ดินเพราะเราสร้างรูปแปดเหลี่ยมเพื่อสัมผัสพื้นดินให้ใกล้เคียงที่สุด หากไม่มีที่ดินอยู่ตรงหัวมุมเส้นทางอาจใช้เส้นทางสำรองตามที่แสดงทางด้านขวา แต่นั่นก็ยังคงเป็นจำนวนมุมฉากและเส้นทแยงมุมเท่ากันดังนั้นระยะทางจึงไม่เปลี่ยนแปลง


´... p´ทำอะไร
Robert Fraser

@RobertFraser ชื่อทางเทคนิคคือการทำลายอาร์เรย์ ในกรณีนี้มันแค่ทำหน้าที่เป็นrest of argumentsพารามิเตอร์
Neil

@Neil จริงแล้วชื่อเทคนิคที่เป็นพารามิเตอร์ที่เหลือ ไวยากรณ์เดียวกันจะใช้สำหรับผู้ประกอบการแพร่กระจาย (คุณใช้ทั้งสองอย่าง...pในที่ต่าง ๆ ) การทำลายล้างเป็นสิ่งอื่น (แม้ว่าผู้ดำเนินการแพร่กระจายสามารถใช้ในการทำลายล้างได้)
Brian McCutchon

@BrianMcCutchon คุณพูดถูกฉันหมายถึงผู้ประกอบการการแพร่กระจาย แต่การทำลายการทำงานในรายการอาร์กิวเมนต์ต่อไป
Neil

6

Python 3.5, 224, 263, 234 218 ไบต์

เลื่อนออกไปอีก 16 ไบต์โดยกำจัดฟังก์ชั่นที่ซ้อนกันและทำให้เป็นหนึ่งซับ

def h(s,k=0,i=0):w=s.find('\n')+1;x=s.find('X')-w;k=k or x;d=[1,w+1,w,w-1,-1,-w-1,-w,-w+1]*2;u=s[:k]+'o'+s[k+1:];return['X'>s[k]and i<8and(h(u,k+d[i+2],i+2)or h(u,k+d[i+1],i+1)or h(u,k+d[i],i))or'',s][s[k]>'X'and k==x]

ออกไป 29 ไบต์:

def f(s):
 w=s.find('\n')+1;x=s.find('X')-w;d=[1,w+1,w,w-1,-1,-w-1,-w,-w+1]*2
 def h(s,k,i):u=s[:k]+'o'+s[k+1:];return['X'>s[k]and i<8and(h(u,k+d[i+2],i+2)or h(u,k+d[i+1],i+1)or h(u,k+d[i],i))or'',s][s[k]>'X'and k==x]
 return h(s,x,0)

อินพุตเป็นสตริงเดี่ยวโดยใช้ '~' สำหรับมหาสมุทร 'X' สำหรับพื้นดินและ 'o' สำหรับขอบเขต (การใช้ 'X' จะบันทึกไบต์สำหรับ '>' แทน '==')

เวอร์ชัน golfed หักที่มีความคิดเห็น:

def f(s):
    w=s.find('\n')+1                         # width of one row
    x=s.find('X')-w                          # starting point
    d=[1,w+1,w,w-1,-1,-w-1,-w,-w+1]*2        # delta to add to current index to move in 
                                             # the 8 directions: E, SE, S, SW, W, NW, 
                                             # N, NE. Make it long to avoid
                                             # lots of modulo operations in 
                                             #    the recursive calls

    def h(s,k,i):                            # s is the island string, k the current
                                             # position, i the direction index
        if s[k]>'X'and k==x:                 # if back at the begining,
            return s                         #   return the map

        elif 'X'>s[k] and i<8:               # if there is water here, and haven't
                                             #  looped around,
            u=s[:k]+'o'+s[k+1:]              #  make a new map with an 'o' in the 
                                             #  current spot

            r = h(u,k+d[i+2],i+2)            # try a 90 degree right turn
            if r: return r

            r = h(u,k+d[i+1],i+1)            # try a 45 degree turn
            if r: return r

            r= h(u,k+d[i],i)                 # try straight ahead
            if r: return r

        return ''                            # this path failed

    return h(s,x,0)

@DLosc แก้ไขแล้ว (ฉันควรลบคำตอบเก่าหรือไม่)
RootTwo

ดี! (ใช่คุณควรลบคำตอบเก่า - หากใครต้องการเห็นมันพวกเขาสามารถดูประวัติการแก้ไขของโพสต์ได้)
DLosc

5

C # 7 - 414 369 327 ไบต์

แก้ไข : เปลี่ยนเป็น 1D วนซ้ำการคำนวณiและjการเดินทาง

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

using C=System.Console;class P{static void Main(){var D=C.In.ReadToEnd().Replace("\r","");int W=D.IndexOf('\n')+1,H=D.Length,z=H,k,q,c;int P()=>z%W*(k%3-1)+z/W*(k/3-1)+H;var B=new int[9];for(;z-->0;)for(k=9;k-->0&D[z]%7<1;)if(B[k]<=P())B[k]=P()+1;for(;++z<H;C.Write(q>9?'o':D[z]))for(q=k=9;k-->0;)q*=(c=P()-B[k])>0?0:c<0?1:2;}}

ลองใช้ออนไลน์

โปรแกรมที่สมบูรณ์จะใช้เวลาการป้อนข้อมูลในมาตรฐานพิมพ์มันจะออกมาตรฐานการใช้งาน#, และ. oสำหรับแต่ละเซลล์ก็คำนวณ 'รายละเอียด' (ซึ่งเป็นระยะทางกว่า 8 ทิศทาง (มันจะปรากฏขึ้นในการคำนวณเก้าเพื่อความสะดวก แต่นี้อยู่เสมอ0) และมีการบันทึกสูงสุดของแต่ละเหล่านี้. มันแล้วเขียนออกแผนที่ทั้งหมด อีกครั้งและแทนที่เซลล์ใด ๆ ที่อยู่ในขอบเขตและไม่ได้อยู่นอกด้วย 'o' รหัสความคิดเห็นด้านล่างอธิบายว่ามันทำงานอย่างไร

ตามคำตอบของฉันในการบันทึกห่านจากการสูญพันธุ์นี่ทำให้เกิดรูปแปดเหลี่ยมที่เล็กที่สุด

หมายเหตุ : นั่นสำหรับครั้งหนึ่งในชีวิตของฉันฉันใช้บางสิ่งบางอย่างจากทศวรรษปัจจุบันและรหัสนี้ต้องใช้ C # 7 เพื่อรวบรวม หากคุณไม่มี C # 7 จะมีหนึ่งบรรทัดที่จะต้องเปลี่ยนใหม่ซึ่งมีการทำเครื่องหมายไว้อย่างชัดเจนในรหัส

ตัวอย่างการใช้งานและเอาท์พุท:

type t7.txt | IslandGolf1.exe

.........ooooooooooo....
........o....#......o...
.......o...#.#.##...#o..
......o....#.#.###.##.o.
.....o....########.##..o
....o.....############.o
...o.#....############.o
..o#.###.##############o
.o##.##################o
o.####################.o
o..##################..o
o.##################...o
o...################...o
o###################...o
o#####################.o
o.##################..o.
o####################o..
o#...##############.o...
o##...#############o....
o#.....###....#...o.....
.o.....#.........o......
..ooooooooooooooo.......

รูปแบบและรหัสความคิดเห็น:

using C=System.Console;

class P
{
    static void Main()
    {
        // \n 10
        // # 35
        // . 46
        // o 111


        var D=C.In.ReadToEnd().Replace("\r",""); // map

        int W=D.IndexOf('\n')+1, // width
            H=D.Length, // length
            z=H, // position in map (decomposed into i and j by and for P)
            k, // bound index
            q, // bound distance, and later cell condition (0 -> outside, 8 -> inside, >8 -> on boudary)
            c; // (free), comparison store

        // 'indexes' into a profile for the point z at index k
        // effectively {i=z%W,j=z/W,-i,-j,i+j,j-i,-i-j,i-j,0}[k] (inside order is a bit different) (0 const is always treated as 'inside bounds')
        // each non-zero-const entry describes the distance in one of the 8 directions: we want to maximise these to find the 'outer bounds'
        // the non-zero-const bounds describe 8 lines, together an octogen
        int P()=>z%W*(k%3-1)+z/W*(k/3-1)+H; // new C#7 local method syntax (if you don't have C#7, you can test this code with the line below instead)
        //k=0;System.Func<int>P=()=>z%W*(k%3-1)+z/W*(k/3-1)+H; // old lambda syntax (must pre-assign k to make static checker happy)

        var B=new int[9]; // our current bounds, each is initially null (must only call P() when on a #)
        // B[k] starts off a 0, P() has a +H term, and W+(H/W)<H for W >= 3, so B[k] is assigned the first time we compare it (H-i-j always > 0)

        for(;z-->0;) // for each cell
            for(k=9;k-->0& // for each bound
                D[z]%7<1;) // if this cell is #
                if(B[k]<=P())B[k]=P()+1; // update bound if necessary (add one so that we define the bound _outside_ the hashes)
        // z=-1
        for(;++z<H; // for each cell
                C.Write(q>9?'o':D[z])) // print the cell (if q > 9, then we are on the bounds, otherwise, spit out whatever we were before)
            // check we are not 'outside' any of the bounds, and that we are 'on' atleast one of them
            for(q=k=9;k-->0;) // for each bound
                q*=(c=P()-B[k])>0?0: // outside bound (q=0)    (??0 is cheaper than (int) or .Value)
                    c<0?1: // inside (preserve q)
                    2; // on bound (if q != 0, then q becomes > 9)
    }
}

แปดเหลี่ยมที่ใหญ่ที่สุด? หรือเล็กที่สุด
Sarge Borsch

@SargeBorsch ขอบคุณแก้ไขข้อความ
VisualMelon
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.