นี่เป็นต้นไม้จริงหรือ


20

คุณควรเขียนโปรแกรมหรือฟังก์ชั่นที่รับสตริงเป็นอินพุตและเอาต์พุตหรือส่งคืนหากอินพุตเป็นต้นไม้ ASCII

  _
\/  /
 \_/
  |
  |

ต้นไม้ ASCII ประกอบด้วยตัวอักษรและ/ \ | _ spacesnewlines

อักขระที่ไม่ใช่ช่องว่างเชื่อมต่อจุดขอบสองจุดของเซลล์โดยส่วนของเส้น:

  • / เชื่อมต่อมุมซ้ายล่างและมุมขวาบน
  • \ เชื่อมต่อมุมขวาล่างและมุมซ้ายบน
  • | เชื่อมต่อจุดกึ่งกลางของขอบด้านล่างและขอบด้านบน
  • _ เชื่อมต่อมุมซ้ายล่างและมุมขวาล่างและจุดกึ่งกลางของขอบล่าง

(หมายเหตุที่นี้หมายถึงว่า|สามารถเชื่อมต่อกับ|หรือ_แต่ไม่ได้มี/หรือ\.)

ภาพ ASCII เรียกว่าต้นไม้ถ้าใช้กฎต่อไปนี้:

  • ตรงจุดหนึ่ง (รูท) ของอักขระหนึ่งตัวแตะกับขอบด้านล่างของแถวสุดท้าย
  • คุณสามารถเข้าถึงจุดใด ๆ ของส่วนของบรรทัดใด ๆ โดย:

    • เริ่มต้นจากราก
    • ใช้เฉพาะส่วนของเส้น
    • ไม่เคยไปในทิศทางที่ลดลง (ไม่แม้แต่ลงด้านข้าง)

อินพุต

  • สตริงที่ประกอบด้วยอักขระ/ \ | _ spaceและnewlineมีอักขระที่ไม่ใช่ช่องว่างอย่างน้อยหนึ่งตัว
  • คุณสามารถเลือกรูปแบบการป้อนข้อมูลได้สองแบบ:

    • ไม่มีช่องว่างที่ไม่จำเป็นรอบ ๆ ต้นไม้ (ดังที่เห็นในตัวอย่าง)
    • ไม่มีช่องว่างที่ไม่จำเป็นรอบ ๆ ต้นไม้ (ดังที่เห็นในตัวอย่าง) ยกเว้นช่องว่างทางด้านขวาของแถวเพื่อทำให้แถวทั้งหมดมีความยาวเท่ากัน
  • ขึ้นบรรทัดใหม่ต่อท้ายเป็นทางเลือก

เอาท์พุต

  • ค่าความจริงที่สอดคล้องกันถ้าอินพุตเป็นต้นไม้ ascii
  • สอดคล้องfalsyค่าถ้าใส่ไม่ได้เป็นต้นไม้ ASCII

ตัวอย่าง

ต้นไม้ที่ถูกต้อง:

|
  _
\/  /
 \_/
  |
  |
/ /    \/
\ \____/
 \/
 /
/
 \___/
 /   \
 \___/
   |
   |
   __/
 _/
/
____
  \  ___
 \ \/
  \/\_____/
 \/  \/
  \__/
    |
    |

ต้นไม้ไม่ถูกต้อง (พร้อมคำอธิบายเพิ่มเติมซึ่งไม่ใช่ส่วนของอินพุต):

\/
 \_______/
  \__   /
   | \_/    <- reachable only on with downward route
   |
_           <- multiple roots
\/          <- multiple root characters
/\          <- multiple roots
|           <- unreachable part

|
 __/
/           <- unreachable parts
|
\____/
 |  |       <- multiple roots
_\__/       <- unreachable parts (_ and \ don't connect to each other)
|

นี่คือรหัส - กอล์ฟเพื่อให้รายการที่สั้นที่สุดชนะ

คำตอบ:


7

PMA / หอย , 99 93

พิมพ์ 1 หากสอดคล้องกับคำจำกัดความ "tree" หรือ 0 ถ้าไม่ รูปแบบการป้อนข้อมูลที่มีพื้นที่เป็นรูปสี่เหลี่ยมผืนผ้านั้นเป็นที่ต้องการมากกว่าแม้ว่าจะมีค่าใช้จ่ายเพียงไบต์เดียวเท่านั้น (โดยใช้Fตัวเลือก) เพื่อแปลงรุ่นที่ขาดเป็นรูปสี่เหลี่ยมผืนผ้าที่เต็มไปด้วยพื้นที่ซึ่งมีประโยชน์ในการทดสอบ

&
\ |{(\_|\|)d=\||(\\a7|\/d|\_da7)=\\|(\\d|\/a5|\_da5)=\/|(\_lr|\|d|\/l|\\r)=\_},^_!(r.,^ )d~

เวอร์ชันที่ล้าสมัย (สำหรับความสุขในการดูส่วนตัวของฉัน):

F&
\ |
{
  \_ (lr=\_|da5=\/|da7=\\|d=\|) | \/ (l=\_|a5=\/|d=\\) | 
    \\ (r=\_|a7=\\|d=\/) | \|d=(\_|\|)    
}, 
^_ !(r.,^ ) d~

สิ่งนี้กลับกลายเป็นว่าเหมาะสมอย่างยิ่งกับคุณสมบัติภาษาปัจจุบัน น่าเสียดายที่ฉันต้องใช้เวลาสองสามชั่วโมงไล่ล่าบั๊กนับการอ้างอิงก่อนที่มันจะทำงานได้

&ตัวเลือกหมายความว่าการแข่งขันจะต้องประสบความสำเร็จในทุกตัวอักษร จากจุดเริ่มต้นที่ไม่ใช่ช่องว่างแต่ละจุดจะตรวจสอบเส้นทางที่ชี้ลงไปด้านล่าง การสร้างเครื่องจักรสถานะ จำกัด ด้วย regex นั้นสั้นกว่ามากโดยใช้การยืนยันที่นี่=... ที่แถวด้านล่างจะตรวจสอบว่าไม่มีอักขระที่ไม่ใช่ช่องว่างทางด้านขวา


10

Mathematica, 345 300 ไบต์

ยังค่อนข้างยาว แต่ฉันคิดว่ามันเป็นการเริ่มต้น ...

(s=StringSplit;v=Reverse;#=="|"||#=="\\"||#=="/"&[""<>s@#]&&(g={};i=0;(c={i,++j};d={i,j+1/2};e=2d-c;g=Join[g,Switch[#,"|",{d->{1,0}+d},"/",{c->c+1},"\\",{e->{i+1,j}},"_",{c->d,d->e,e->c},_,{}]])&/@Characters[++i;j=0;#]&/@{##};Sort@VertexOutComponent[Graph@g,g[[1,1]]]==Union@@List@@@g)&@@v@s[#,"
"])&

นี่คือรุ่นที่ไม่ได้รับการเคารพเล็กน้อย:

(
  s = StringSplit;
  v = Reverse;
  # == "|" || # == "\\" || # == "/" &[
      "" <> s@#
      ] && (
      g = {};
      i = 0;
      (
           c = {i, ++j};
           d = {i, j + 1/2};
           e = 2 d - c;
           g = Join[g, Switch[#,
              "|", {d -> {1, 0} + d},
              "/", {c -> c + 1},
              "\\", {e -> {i + 1, j}},
              "_", {c -> d, d -> e, e -> c},
              _, {}
              ]]
           ) & /@ Characters[
          ++i;
          j = 0;
          #
          ] & /@ {##};
      Sort@VertexOutComponent[Graph@g, g[[1, 1]]] == 
       Union @@ List @@@ g
      ) & @@ v@s[#, "\n"]
) &

นี้กำหนดฟังก์ชั่นที่ไม่มีชื่อซึ่งจะใช้เวลาสตริงเป็น input และผลตอบแทนหรือTrueFalse

แนวคิดพื้นฐานแรกคือการตรวจสอบว่ามีรากเดียวและจากนั้นสร้างวัตถุจริง (กำกับ) Graphเพื่อตรวจสอบว่าสามารถเข้าถึงจุดยอดทั้งหมดจากรากได้หรือไม่ นี่คือวิธีที่เราสร้างกราฟ:

ลองนึกภาพกริดจำนวนเต็มที่ซ้อนทับบนศิลปะ ASCII โดยที่พิกัดจำนวนเต็มสอดคล้องกับมุมของเซลล์อักขระ จากนั้นในแต่ละเซลล์มีจุดที่เกี่ยวข้องหกจุดที่สามารถเชื่อมต่อได้ นี่คือตัวอย่างที่ผมเคยมีป้ายกำกับยังจุดaที่จะf:

     |                 |
     |                 |
---(2,3)---(2.5,3)---(3,2)---
     | d      e      f |
     |                 |
     |                 |
     |                 |
     |                 |
     |                 |
     |                 |
     | a      b      c |
---(2,2)---(2.5,2)---(3,2)---
     |                 |
     |                 |

ดังนั้นเราสามารถสร้างกราฟที่มีจุดยอดเป็นพิกัดครึ่งจำนวนเต็มและมีขอบถูกกำหนดโดยอักขระที่ไม่ใช่ช่องว่างในอินพุต |เชื่อมต่อbไปe, /เชื่อมต่อaไปfและ\เชื่อมต่อไปยังc dโปรดทราบว่าสิ่งเหล่านี้จะต้องถูกนำไปที่ขอบเพื่อให้แน่ใจว่าเราจะไม่เลื่อนลงมาในขณะที่สำรวจกราฟในภายหลัง สำหรับ_เราสามารถไปทางใดทางหนึ่งดังนั้นในทางทฤษฎีเราต้องสี่ขอบa -> b, b -> a, ,b -> c c -> bแต่เราสามารถสังเกตเห็นว่าทุกสิ่งที่สำคัญคือการที่มีวงจรที่มีทั้งสามจุดเพื่อให้เราสามารถลดระยะนี้ถึงสามขอบ: a -> b, ,b -> cc -> a

การสร้างกราฟนี้ค่อนข้างง่ายใน Mathematica เพราะวัตถุใด ๆสามารถทำหน้าที่เป็นจุดสุดยอดได้ดังนั้นฉันจึงสามารถสร้างกราฟที่มีจุดยอดเป็นคู่พิกัดได้

ในที่สุดเราตรวจสอบว่าทุกจุดสุดยอดสามารถเข้าถึงได้จากราก พิกัดของรูตนั้นหาได้ง่ายเนื่องจากจุดสุดยอดแรกที่เราเพิ่มเข้าไปในกราฟ จากนั้นวิธีที่สั้นที่สุดที่ฉันพบเพื่อตรวจสอบว่าจุดยอดทั้งหมดสามารถเข้าถึงได้หรือไม่เพื่อตรวจสอบว่าVertexOutComponentรูต (เช่นชุดของจุดยอดทั้งหมดที่เข้าถึงได้จากรูท) นั้นเหมือนกับชุดของจุดยอดทั้งหมดในกราฟหรือไม่


1
300 ไบต์อาจมีความยาว แต่แน่นอนว่าเป็น 300 ที่น่าพอใจ!
Alex A.

2

ทับทิม 226 227 228

->i{w=i.index(?\n)+1
t=[i.index(/[^ _] *\n\z/)]
a=->x,c{(i[x]==c||i[x]==?_)&&t<<x}
((x=t.pop)&&(s=x-w;c=i[x])<?0?(a[s+1,?/];a[s,?\\]):c<?]?(a[s-1,?\\];a[s,?/]):c<?`?(a[x-1,?\\];a[x+1,?/]):a[s,?|]
i[x]=' ')while t!=[]
!i[/\S/]}

การทดสอบออนไลน์: http://ideone.com/Z7TLTt

โปรแกรมทำสิ่งต่อไปนี้:

  • ค้นหาราก (ก\, /หรือ|ในแถวสุดท้าย)
  • เริ่มต้นจากรากนั้นไต่ต้นไม้โดยใช้กฎและแทนที่ถ่านทุกอันที่มีพื้นที่ว่าง
  • ในตอนท้ายดูว่าสตริงของเราประกอบด้วยช่องว่าง (หมายถึงต้นไม้ที่ถูกต้อง) หรือไม่ (ต้นไม้ที่ไม่ถูกต้อง; ไม่ใช่ทุกชิ้นที่ "เยี่ยมชม")

นี่มัน ungolfed:

F =-> input {
  row_size = input.index(?\n)+1

  root_coord = input.index /[^ _] *\n\z/

  # coordinates to process
  todo = [root_coord]

  add_todo = -> coord, char{
    if input[coord] == char || input[coord] == ?_
      todo << coord
    end
  }

  while todo.any?
    x = todo.pop

    next unless x # exit quickly if no root present

    case input[x]
    when ?|
      add_todo[x - row_size, ?|]
    when ?_
      add_todo[x - 1, ?\\]
      add_todo[x + 1, ?/]
    when ?/
      add_todo[x - row_size + 1, ?/]
      add_todo[x - row_size, ?\\]
    when ?\\
      add_todo[x - row_size - 1, ?\\]
      add_todo[x - row_size, ?/]
    end
    input[x]=' '
  end
  input.strip < ?*
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.