ค้นหาเส้นทาง!


10

คุณต้องเขียนโปรแกรมหรือฟังก์ชั่น

อินพุตเป็น 'แผนที่' ของตัวเลข คุณสามารถเลือกที่จะใช้แผนที่เป็นสตริงที่มีอักขระบรรทัดใหม่ ( \n) หรืออาร์เรย์ของสตริง 2D

แผนที่ทั้งหมดเป็น 5 ตัวอักษร 5 ตัวและตัวละครจะเป็นตัวเลขมากกว่า 0 หรือเว้นวรรคเสมอ

นี่คือตัวอย่างของแผนที่:

12 45
11233
  233
    1
2 899

งานของคุณคือการค้นหาส่วนประกอบที่เชื่อมต่อในแผนที่ ส่วนประกอบที่ถูกต้องคือชุดของอย่างน้อยสามแนวนอนและ / หรือแนวตั้ง ( ไม่ใช่แนวทแยงมุม ) ตัวเลขที่เหมือนกันที่เชื่อมต่อ ( ไม่เว้นวรรค ) จากนั้นคุณจะต้องแทนที่อักขระของส่วนประกอบที่เชื่อมต่อที่ถูกต้องด้วยxs และพิมพ์หรือส่งคืนผลลัพธ์นั้น

ดังนั้นผลลัพธ์สำหรับตัวอย่างข้างต้นจะเป็น:

x2 45
xx2xx
  2xx
    1
2 899

นี่คืออีกกรณีทดสอบ (ขอบคุณ Martin Ender):

Input:
2   3
    4
 1  5
111 6
11  7

Output:
2   3
    4
 x  5
xxx 6
xx  7

นี่คือโค้ดกอล์ฟที่สั้นที่สุดในหน่วยไบต์!



ได้รับอนุญาตในตัว?
Ioannes

@ โจแอนใช่
Daniel

คำตอบ:


1

JavaScript (ES6), 171 161 139 137 136 133 132 ไบต์

f=(a,i=0)=>(F=i=>" "<c&&a[i]===c&&(a[i]=n,1+F(i-1)+F(i+1)+F(i-6)+F(i+6)),n=1,c=a[i],n=F(i)>2?"x":c,c=1,F(i),i>28?a:f(a,++i+(i%6>4)))
<!-- this HTML included just for testing --><textarea rows=5 cols=6 oninput="document.querySelector`pre`.innerHTML=this.value.length==29?f([...this.value]).join``:'invalid input'">12 45&#10;11233&#10;  233&#10;    1&#10;2 899</textarea><br/><pre></pre>

นี่คือคำแปลของคำตอบ Python ของฉัน I / O เป็นอาร์เรย์อักขระ

น่าเสียดายที่ไม่มีวิธีการที่มีประสิทธิภาพในการทำsum...


5

Python 3, 238 237 200 199 192 181 ไบต์

def f(a,i=0):F=lambda i,n,c:29>i>=0!=" "!=a[i]==c!=n and(a.__setitem__(i,n)or-~sum(F(i+j,n,c)for j in[-1,1,-6,6]));j=i+i//5;F(j,[a[j],"x"][2<F(j,1,a[j])],1);i>23or f(a,i+1);return a

กำหนดฟังก์ชั่นf(a)ที่รับอินพุตเป็นอาเรย์ของอักขระและส่งคืนอาเรย์ตัวเดียวกันที่ถูกแก้ไข ( อาร์เรย์ของอักขระสามารถยอมรับได้เป็นสตริงตามค่าเริ่มต้น )

ไม่พอใจกับคำอธิบาย

รหัสที่แก้ไขจะเรียกซ้ำ แต่ใช้งานได้เหมือนกัน

# The main function; fills all continuous nonempty areas of size >= 3 in array
# with x's. Both modifies and returns array.
def findpaths(array):
    # Fills a continuous area of curr_char in array with new_char, starting
    # from index. Returns the number of cells affected.
    def floodfill(index, new_char, curr_char):
        if (0 <= index < 29                   # Check that the position is in bounds
                and (index + 1) % 6 != 0      # Don't fill newlines
                and array[index] != " "       # Don't fill empty cells
                and array[index] == curr_char # Don't fill over other characters
                and curr_char != new_char):   # Don't fill already filled-in cells
            array[index] = new_char # Fill current position
            return (1 # Add neighboring cells' results, plus 1 for this cell
                    + floodfill(index + 1, new_char, curr_char)  # Next char
                    + floodfill(index - 1, new_char, curr_char)  # Previous char
                    + floodfill(index + 6, new_char, curr_char)  # Next line
                    + floodfill(index - 6, new_char, curr_char)) # Previous line
        return 0 # Nothing was filled. The golfed solution returns False here,
                 # but that's coerced to 0 when adding.

    for i in range(25): # Loop through the 25 cells
        i += i // 5 # Accommodate for newlines in input
        curr_char = array[i] # Get the cell's contents
        # Fill the area from the cell with dummies
        area_size = floodfill(i, 1, curr_char)
        # Convert dummies to "x" if area was large enough, back to original otherwise
        fill_char = "x" if 2 < area_size else curr_char
        floodfill(i, fill_char, 1)
    return array

2 ไบต์เพื่อเอาชนะ mathematica solution ...
FlipTack

1
@FlipTack ใช่ ฉันไม่คิดว่ามันจะเกิดขึ้นในวันนี้ แต่ฉันกำลังแปลสิ่งนี้ให้กับ JS และดูเหมือนว่าจะมีแนวโน้ม
PurkkaKoodari

3

ทับทิม, 304 ไบต์

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end
def b2(s,i,c)
  if(0...s.size)===i&&s[i]==c&&!@v[i]
    @v[i]=s[i]='x'
    [1,-1,6,-6].each{|j|b2(s,i+j,c)}
  end
  s
end
def f(s)
  z = s.dup
  ps = ->(i){b(z.dup,i).scan('x').size}
  (0...s.size).each{|i|b(s, i)if ![' ',"\n"].include?(s[i])&&ps.call(i)>2}
  s
end

ตัวอย่างการใช้งาน:

puts f(File.read("map.txt"))

โค้ดจะใช้วิธี 'blot' เพื่อคำนวณความยาวพา ธ

ตัวแปร / วิธีการ:

  • f (s): ฟังก์ชันในการแปลงสตริงแผนที่ส่งคืนแผนที่ใหม่ด้วย 'x's
  • ps (i): ขนาดพา ธ จากดัชนีแผนที่ i (โดยที่ x = i% 6, y = i / 6)
  • s: สตริงอินพุต, แผนที่เส้นคั่นด้วย "\ n"
  • z: สำเนาของสตริงอินพุต
  • b (s, i): ฟังก์ชั่น 'blot': เขียน 'x' จากดัชนีแผนที่ฉันบนพา ธ
  • @v: อาร์เรย์ 'เข้าชม'

พยายามอธิบายรายละเอียดเพิ่มเติม:

ทำสำเนาของสายป้อนซึ่งเราใช้สำหรับการค้นหาความยาวของเส้นทางจากจุดที่กำหนดในแผนที่

z = s.dup

กำหนดฟังก์ชั่นไม่ระบุชื่อ 'ps' (ความยาวเส้นทาง) (แลมบ์ดา) ซึ่งใช้ดัชนีแผนที่ i เป็นอาร์กิวเมนต์ มันคืนความยาวของเส้นทางจากจุดนั้น มันทำได้โดยเรียกเมธอด 'b' (blot) เพื่อแทรก x บนสำเนาของแผนที่ต้นฉบับแล้วนับจำนวน x ในสตริงที่ส่งคืน

  ps = ->(i){b(z.dup,i).scan('x').size}

ส่วนต่อไปนี้วนซ้ำอักขระแต่ละตัวในแผนที่ (ดัชนี i, อักขระ s [i]) มันเรียกฟังก์ชัน 'b' (blot) บนตำแหน่งแผนที่ i หากความยาวพา ธ จากตำแหน่ง i มากกว่า 2 และหากไม่ใช่ช่องว่างหรืออักขระขึ้นบรรทัดใหม่

  (0...s.size).each { |i|
     b(s, i) if ![' ',"\n"].include?(s[i]) && ps.call(i) > 2
  }

ฟังก์ชั่น b (หยด) ใช้สตริงแผนที่และดัชนีเป็นอาร์กิวเมนต์ มันเริ่มต้น @ v (เยี่ยมชมอาร์เรย์) และเรียกฟังก์ชั่นผู้ช่วย b2

def b(s,i)
  @v=[]
  b2(s,i,s[i])
end

ฟังก์ชั่น b2 รับสตริงแผนที่ตำแหน่งแผนที่ (i) และตัวละครในเส้นทางปัจจุบัน (c) มันเรียกตัวเองซ้ำเพื่อแทนที่ส่วนที่เชื่อมต่อของตัวเลขด้วยอักขระ 'x' มันจะส่งกลับสตริงการป้อนข้อมูล (นี่คือฟังก์ชั่น ps สามารถเรียกสแกน () กับค่าที่ส่งคืน)

ถ้าข้อความนี้ตรวจสอบว่าตำแหน่งแผนที่ (i) ที่กำหนดอยู่ภายในขอบเขตของสตริง (0 ... s.size) และอักขระที่ s [i] นั้นเหมือนกับอักขระเริ่มต้น ยัง @v [i] ถูกตรวจสอบเพื่อหลีกเลี่ยงการเรียกซ้ำไม่สิ้นสุด

if(0...s.size) === i && s[i] == c && !@v[i]

นี่คือบิตที่แทนที่อักขระที่ index (i) ด้วยอักขระ 'x' มันยังทำเครื่องหมายดัชนีนั้นเมื่อเข้าเยี่ยมชม

@v[i] = s[i] = 'x'

นี่คือที่ b2 เรียกตัวเองค้นหาเส้นทางซ้ำ ๆ i + 1 คืออักขระหนึ่งตัวทางขวา i-1 คืออักขระหนึ่งตัวทางซ้าย i + 6 คือหนึ่งแถวลง (5 หลัก + 1 บรรทัดใหม่ = 6 อักขระ), i-6 คือหนึ่งแถวขึ้นไป

[1,-1,6,-6].each { |j| b2(s, i+j, c) }

1

C (Ansi), 243 233 179 188 ไบต์

แข็งแรงเล่นกอล์ฟ:

#define O o[1][l]
x,n,l,L;r(o,l)char**o;{if(!(l>L|l<0|O<47|O!=x))n++,O++,r(o,l-1),r(o,l+6),r(o,l-6),r(o,l+1),n>2?O='x':O--;}main(g,o)char**o;{for(;(L=30)>l;l++)n=0,x=O,r(o,l);puts(o[1]);}

ด้วยคำอธิบายประกอบ:

#define O o[1][l]
x,n,l,L;      /*-------------------------- Globals*/
r(o,l)char**o;{ /*------------------------ Recursive Function*/
    if(!(l>L|l<0|O<47|O!=x)) /*----------- if this cell is valid(in
                                              range, is a number, is the 
                                              same as the parent number*/
    n++,     /*--------------------------- Increment count*/
    O++,     /*--------------------------- Increment character to mark*/
    r(o,l-1),  /*------------------------- Recurse left*/
    r(o,l+6),  /*------------------------- Recurse down*/
    r(o,l-6),  /*------------------------- Recurse down*/
    r(o,l+1),  /*------------------------- Recurse right*/
    n>2?O='x':O--;  /*---------------------If greater than 3, replace with x, else decrement character*/ 
}          /*----------------------------- Return*/

main(g,o)char**o;{ /*--------------------- Main*/
    for(;l<(L=30);l++){ /*---------------- For entire string and set L*/
        n=0;
        x=O;        /*-------------------- set counter to 0*/
        r(o,l); /*------------------------ Recurse*/
    } /*---------------------------------- End While*/
    puts(o[1]); /*------------------------ Print*/

}

การป้อนข้อมูล:

คาดว่าจะมีการขึ้นบรรทัดใหม่ที่จุดเริ่มต้นและจุดสิ้นสุดของสตริง

อินพุตตัวอย่าง:

./findPaths "
12 45
11233
  233
    1
2 899
"

ตัวอย่างผลลัพธ์:

x2 45
xx2xx
  2xx
    1
2 899

ปรับปรุง

การแก้ไขกริดทำให้ฉันสามารถโกนหนวดได้เกือบ 60 ไบต์


ฉันเดาว่าฉันสามารถบันทึกได้ 22 ตัวอักษรถ้าฉันเปลี่ยนสิ่งนี้เป็นขนาดแผนที่การแก้ไข - ฉันจะเปลี่ยนที่ถ้าฉันพบสิ่งอื่นที่ฉันต้องการเปลี่ยน
dj0wns

1

Mathematica ขนาด 180 ไบต์

(f=Flatten@#;p=Partition)[If[Tr[1^VertexComponent[r~Graph~Cases[##&@@p[#,2,1]&/@Join[g=p[r,5],g],{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ":>a<->b],#]]<3,f[[#]],"x"]&/@(r=Range@25),5]&

คำอธิบาย:

(f=Flatten@#;p=Partition)[
  If[
    Tr[1^VertexComponent[
        r~Graph~Cases[
          ##&@@p[#,2,1]&/@Join[g=p[r,5],g],
          {a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ":>a<->b
        ],
        #
      ]]<3,
    f[[#]],
    "x"
  ]&/@(r=Range@25),
  5
]&

ฟังก์ชั่นบริสุทธิ์ซึ่งยอมรับ5x5อาร์เรย์ เป็น 3 ไบต์ส่วนตัวใช้ตัวอักษรที่เป็นตัวแทนของผู้ประกอบการU+F3C7 postfix transpose\[Transpose]

(f=Flatten@#;p=Partition): flattens fรายการการป้อนข้อมูลและเก็บไว้ใน ตั้งค่าp = Partitionและส่งคืน

g=p[r,5]: อาร์เรย์{{1,2,3,4,5}, ..., {21,22,23,24,25}}(นี่เป็นเพราะrตั้งค่าเป็นRange@25)

Join[g=p[r,5],g]: gรายการของแถวและคอลัมน์ของ

p[#,2,1]&: ฟังก์ชั่นบริสุทธิ์ซึ่งพาร์ทิชันรายการ#ลงในรายการย่อยของความยาว2ด้วยการทับซ้อน1; #คือรายชื่อของคู่ที่อยู่ติดกันใน

##&@@p[#,2,1]&: Sequenceเหมือนข้างบนยกเว้นว่ามันจะส่งกลับ

##&@@p[#,2,1]&/@Join[g=p[r,5],g]: แผนที่ฟังก์ชั่นก่อนหน้าของแถวและคอลัมน์ของการขอรับรายการทั้งหมดของรายการที่อยู่ติดกันในg gไส้ของฉันบอกว่ามีวิธีที่สั้นกว่าในการทำเช่นนี้

r~Graph~Cases[...]: กราฟที่มีจุดยอดเป็นจำนวนเต็ม1, ..., 25และมีขอบเป็นขอบระหว่างรายการที่อยู่ติดกันgซึ่งมีรายการที่สอดคล้องกันในอาร์เรย์อินพุต (นอกเหนือจาก" ")

{a_,b_}/;(A=f[[a]])==f[[b]]&&A!=" ": รูปแบบซึ่งตรง{a,b}เช่นที่f[[a]] == f[[b]](ค่าเดียวกันในอาร์เรย์การป้อนข้อมูล) " "และที่ไม่ได้เท่ากับ ตั้งค่าA = f[[a]]ให้บันทึก1ไบต์

...:>a<->b: แทนที่ทุกนัดด้วยขอบที่ไม่ได้บอกทิศทางจาก a ถึง b

VertexComponent: ส่งคืนส่วนประกอบที่เชื่อมต่อของอาร์กิวเมนต์ที่สอง (จุดสุดยอด) ในอาร์กิวเมนต์แรก (กราฟ)

Tr[1^VertexComponent[...]]: ขนาดของส่วนประกอบที่เชื่อมต่อ บันทึกไบต์จาก1Length@VertexComponent[...]

If[Tr[...]<3,f[[#]],"x"]&: ฟังก์ชั่นเพียวซึ่งจะนำเข้าใน# gหากขนาดของส่วนประกอบที่เชื่อมต่อมีค่าน้อยกว่า3ให้แทนที่ด้วยรายการที่สอดคล้องกันในอินพุต "x"มิฉะนั้นแทนที่ด้วย

(f=Flatten@#;p=Partition)[...,5]: และในที่สุดก็ก่อร่างใหม่ผลลัพธ์ที่จะเป็น5x5อาร์เรย์


0

Clojure 188 ไบต์

นี่ค่อนข้างท่วมท้น: D

#(apply str(map-indexed(fn[i v](if((set(flatten(for[m(range 30)](let[n(for[p[-1 -6 1 6]:when(=(get %(+ m p)0)((set"123456789")(% m)))](+ m p))](if(< 1(count n))(conj n m)[])))))i)\x v))%))

เรียกสิ่งนี้ว่า (ต้องใช้อักขระ 1D ของตัวอักษร):

(def f #(apply str(...))

(print (str "\n" (f (vec (str "12 45\n"
                              "11233\n"
                              "  233\n"
                              "    1\n"
                              "2 899\n")))))

(print (str "\n" (f (vec (str "2   3\n"
                              "    4\n"
                              " 1  5\n"
                              "111 6\n"
                              "11  7\n")))))

ขี้เกียจเกินกว่าที่จะคลายมัน แต่โดยทั่วไปfor[m(range 30)]ไปที่แต่ละดัชนีและสำหรับแต่ละดัชนีด้านในlet[n(for[p[-1 -6 1 6]...(+ m p))]จะทำรายการองค์ประกอบ 0 ถึง 4 ซึ่งแสดงรายการสถานที่ซึ่งมีค่าเดียวกัน (1 - 9) เป็นตำแหน่งกึ่งกลาง หากมีมากกว่า 1 (if((set(flatten(...)))i)ชิ้นเพื่อนบ้านตรงกลางมันหมายความว่าทุกรูปแบบเหล่านี้คลัสเตอร์เพื่อให้สถานที่เหล่านั้นจะมีการเพิ่มชุดที่ใช้ใน หากiพบดัชนีจากชุดข้อมูล\xจะถูกปล่อยออกมาและค่าดั้งเดิมจะเป็นอย่างอื่น นั่น:when( ... )เป็นเรื่องที่น่าสนใจมาก ...

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