มันเป็นต้นไม้เชิงเส้น (ฉบับที่กว้างแรก)


11

พื้นหลัง

ต้นไม้ที่ไม่มีป้ายกำกับอาจมีลักษณะเช่นนี้:

   o
 / | \
o  o  o
|    / \
o   o   o

ในการทำให้ต้นไม้นี้เป็นเส้นตรงเราต้องติดป้ายแต่ละโหนดoด้วยจำนวนของโหนดลูก:

   3
 / | \
1  0  2
|    / \
0   0   0

จากนั้นเขียนตัวเลขลงในรายการในลักษณะลมหายใจก่อนหมายถึงบรรทัดต่อบรรทัดและจากซ้ายไปขวา:

[3, 1, 0, 2, 0, 0, 0]

นี่คือการแสดงที่ไม่เหมือนใครและไม่ซ้ำใครของต้นไม้ด้านบนซึ่งหมายความว่าไม่มีต้นไม้บริสุทธิ์ที่แตกต่างกันสองตัวที่จะมีเส้นตรงเหมือนกันและเราสามารถสร้างต้นไม้ดั้งเดิมขึ้นใหม่จากรายการ

แม้ว่าต้นไม้แต่ละต้นจะสอดคล้องกับรายการจำนวนเต็มจำนวนหนึ่ง แต่ไม่ใช่รายการจำนวนเต็มแต่ละรายการที่แสดงถึงต้นไม้เชิงเส้นที่ถูกต้อง: ตัวอย่างเช่น[2, 0, 0, 0]ไม่ได้เป็นตัวแทนของต้นไม้ที่ถูกต้องถ้าเราพยายามที่จะทำให้เป็นเส้นตรง

[2,0,0,0] -> 2 [0,0,0] -> 2 [0,0] -> 2 [0]
            / \          / \        / \
                        0          0   0

แต่ยังมี0เหลืออยู่ในรายการและไม่มีที่จะวาง ในทำนองเดียวกัน[2, 0]ไม่ได้เป็นต้นไม้เชิงเส้นที่ถูกต้องเช่นกันในขณะที่ต้นไม้ de-linearized มีจุดเด็กที่ว่างเปล่า:

  2
 / \
0

งาน

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

อินพุต: รายการที่ไม่ว่างเปล่าของจำนวนเต็มไม่เป็นลบ

เอาท์พุท: ค่าความจริงถ้ารายการคือการทำให้เป็นเชิงเส้นของต้นไม้ค่าเท็จอื่น ๆ

Testcases

Truthy
[0]
[2, 0, 0]
[1, 1, 1, 1, 1, 0]
[3, 1, 0, 2, 0, 0, 0]
[2, 0, 2, 2, 0, 0, 2, 0, 0]
[3, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0]
[1, 5, 3, 0, 2, 1, 4, 0, 1, 0, 0, 2, 1, 0, 0, 1, 1, 0, 0, 0, 0, 2, 1, 0, 0, 1, 0]
Falsy
[0, 1]
[2, 0]
[2, 0, 0, 0]
[1, 0, 1]
[3, 2, 1, 0]
[2, 0, 0, 2, 0, 0]
[4, 1, 0, 3, 0, 0, 0, 0]
[4, 2, 0, 3, 1, 0, 0, 0, 0, 0]

คำตอบ:


4

Haskell, 44 ไบต์

f[n:k]=iterate f[k]!!n
f _=[]
g x=f[x]==[[]]

นิยามฟังก์ชันgที่รับรายการและส่งคืนบูลีน เห็นมันผ่านกรณีทดสอบทั้งหมด

คำอธิบาย

สิ่งนี้ขึ้นอยู่กับความจริงที่ว่าการสร้างลิเนียร์เชิงเส้นแรกและเชิงกว้างแรกสร้างอาร์เรย์เดียวกัน ดูคำตอบของ Martin สำหรับรายละเอียด; โดยพื้นฐานแล้วพวกเขาทั้งสองให้เงื่อนไขเกี่ยวกับคณิตศาสตร์แบบเดียวกันกับอาร์เรย์

ฟังก์ชั่นfจะได้รับรายการอินพุตที่อยู่ในรายการเดี่ยว มันจะปรากฏหนึ่งหมายเลขnออกจากรายการแล้วเรียกตัวเองnครั้งในรายการที่เหลือเพื่อประมวลผลลูกของโหนด popped (ความลึกก่อน) การเปิดรายการว่างจะทำให้เกิดผลลัพธ์[]ซึ่งฉันใช้เป็นสถานะข้อผิดพลาด ฟังก์ชั่นgตรวจสอบว่าผลลัพธ์สุดท้ายคือ[[]]สถานะที่ไม่ผิดพลาดที่ไม่ซ้ำกันและไม่มีโหนดที่ไม่ได้ประมวลผล หาก Haskell ถูกพิมพ์อย่างอ่อนฉันก็สามารถใช้0หรือบางสิ่งบางอย่างในสถานะข้อผิดพลาดและไม่จำเป็นต้องตัดอินพุตลงในรายการอื่น


3

Mathematica, 38 ไบต์

Last@#<0<=Min@Most@#&@Accumulate[#-1]&

แนวคิดพื้นฐานคือเราติดตามจำนวนโหนดที่จะเติม แต่ละองค์ประกอบในรายการใช้โหนดเดียวและเพิ่มมากที่สุดเท่าที่มีลูก ดังนั้นแต่ละองค์ประกอบการเปลี่ยนแปลงนับโดยรวมi i-1นับนี้ปิดโดยหนึ่งเพราะควรจะเริ่มต้นจาก1(ราก) 0ไม่

สำหรับต้นไม้ที่ถูกต้องเราก) ไม่สามารถลงไปด้านล่าง0ตลอดรายการเพราะเราไม่มีที่ใดที่จะวางโหนดปัจจุบันและ b) ต้องจบด้วย-1ท้ายที่สุดมิฉะนั้นเราจะเหลือโหนดที่ไม่ได้ใช้

เราได้รับผลรวมการทำงานของโหนดที่เหลือทั้งหมดด้วยAccumulate[#-1](ซึ่งคำนวณจำนวนเงินนำหน้าของรายการอินพุตลบหนึ่ง) และจากนั้นเราจะตรวจสอบว่าองค์ประกอบที่ผ่านมาและเพียงองค์ประกอบสุดท้ายคือ-1ด้วย:

Last@#<0<=Min@Most@#

โปรดทราบว่าการตรวจสอบว่าองค์ประกอบสุดท้ายเป็นลบนั้นเพียงพอเนื่องจากเราไม่สามารถลดลงได้มากกว่า1ดังนั้นหากค่าสุดท้ายเป็น-2หรือต่ำกว่ามันจะเป็นไปไม่ได้ที่ค่าต่ำสุดจะไม่เป็นค่าลบ


2

เรติน่า 29 ไบต์

\d+
$*
^(?<-1>(1)*,)*$(?(1)!)

ลองออนไลน์! (บรรทัดแรกเปิดใช้งานชุดทดสอบที่แยกบรรทัดด้วยฟีด)

คำอธิบาย

แนวคิดพื้นฐานเหมือนกับคำตอบ Mathematica ของฉัน : เราติดตามจำนวนโหนดที่เหลือทั้งหมดที่กำลังทำงานอยู่ตรวจสอบให้แน่ใจว่ามันจะไม่ต่ำกว่าศูนย์ แต่จบลงที่ศูนย์ อย่างไรก็ตามวิธีการใช้งานกับ regex นั้นแตกต่างกันมาก

\d+
$*

สิ่งนี้จะแปลงอินพุตเป็นเอกภาพโดยเปลี่ยนจำนวนเต็มnเป็นn1s

^(?<-1>(1)*,)*$(?(1)!)

นี่คือสิ่งที่เวทมนตร์ที่แท้จริงเกิดขึ้น มันเป็น regex สั้น ๆ ที่ค่อนข้างตรงกับต้นไม้ที่ใช้ได้ แต่กลไกของมันค่อนข้างบอบบาง

ฉันใช้กลุ่มที่สมดุลเพื่อติดตามจำนวนโหนดซึ่งเป็นวิธีการทำงานกับสแต็คภายใน regex

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

ดังนั้นนี่คือรายละเอียดของ regex:

^        e# Anchor the match to the beginning of the string.
(?<-1>   e# Each repetition of this group will match one number. 
         e# We can ignore the <-1> for now.
  (1)*   e#   Match each unary digit of the current number, pushing
         e#   a capture onto stack 1. This increments our total of
         e#   remaining nodes by 1 for each child.
  ,      e#   Match a comma. Note that this requires that there is at
         e#   least one more number in the list.
)*       e# At the end of the repetition the <-1> pops one capture from
         e# the stack. This is the node that the current number itself
         e# takes up.
$        e# Match the end of the string. This requires the input to end
         e# in a zero, because the last thing we matched was a comma.
(?(1)!)  e# Make sure that stack 1 is empty, so that we don't have any
         e# unused nodes.

1

CJam (20 ไบต์)

{X0@{+\(_0>{\}*}/|!}

ชุดทดสอบออนไลน์ นี่คือบล็อกแบบไม่ระบุชื่อซึ่งใช้อาร์เรย์ในสแต็กและปล่อย 0 หรือ 1 บนสแต็ก

การผ่า

ใน pseudocode นี่คือ:

p = 1
q = 0
foreach (i in input):
  q += i
  if (--p <= 0):      # in practice, if (--p == 0):
      p, q = q, p
return (p | q) == 0   # i.e. p == 0 && q == 0

qสะสมผลรวมของเลเบลของโหนดที่ระดับปัจจุบันในทรี pนับถอยหลังโหนดที่เหลืออยู่ในระดับปัจจุบัน


{X0@{+\(_{\}&}/|!}ฉันคิด?
Martin Ender

@นอกจากนี้ยังดูเหมือนว่าคุณควรจะสามารถที่จะบันทึกไบต์โดยใช้โปรแกรมเต็มรูปแบบที่จะหลีกเลี่ยง
Martin Ender

1

เขาวงกต 17 ไบต์

(
+?
;-)
,_"
@@,!

ลองออนไลน์!

เอาท์พุทจริง-1และเอาท์พุทเท็จจะว่างเปล่า การกำหนดความจริงและความเท็จใน Labyrinth นั้นค่อนข้างยุ่งยากเพราะกิ่งก้านของ Labyrinth ส่วนใหญ่เป็นแบบไตรภาค อย่างไรก็ตามวิธีเดียวในการสร้างเงื่อนไขที่มีสองสาขาที่เชื่อถือได้คุณสามารถทำได้:

>"F
 T

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

คำอธิบาย

อัลกอริทึมยังคงเหมือนเดิมในคำตอบ Mathematica และ Retina ของฉัน แต่เนื่องจากกระแสการควบคุมของเขาวงกตมันจึงทำงานแตกต่างกันเล็กน้อยในเวลานี้:

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

    1. เรากด EOF ก่อนถึงจำนวนศูนย์ทั้งหมด ในกรณีนั้นมีโหนดที่ไม่ได้ใช้เหลืออยู่และเราไม่ได้พิมพ์อะไรเลย
    2. เราไปถึงศูนย์และเราอยู่ที่ EOF ในกรณีนี้เรามีแผนผังที่ถูกต้อง
    3. เราไปถึงศูนย์และยังไม่ถึง EOF ในกรณีนี้เราไม่มีโหนดก่อนที่จะครอบคลุมองค์ประกอบทั้งหมดและเราไม่พิมพ์อะไรเลย

สำหรับรหัสจริงเราเริ่มที่มุมซ้ายบน การ(เปลี่ยนศูนย์โดยนัยที่ด้านบนของสแต็กเป็น a -1ซึ่งจะเป็นผลรวมการทำงาน จากนั้นเราเข้าสู่ลูปหลักที่แน่นมากของโปรแกรม+?-)"_,;+:

+   Add the top two values. This does nothing on the first iteration,
    but gets rid of a helper-zero on subsequent iterations.
?   Read and push integer.
-   Subtract it from running total.
)   Increment.
"   No-op. There is a branch at this point. If the running total is zero,
    we move straight ahead onto the , (see below). Otherwise, the loop continues.
_   Push a zero. This is necessary to prevent the IP from turning south.
,   Read a character. This will either be the next separator (some positive
    number) or EOF (-1). If it's EOF, the IP turns south and the program
    terminates. Otherwise, the loop continues.
;   Discard the separator.

นั่นทำให้เหลือเพียงกรณีที่เราได้ลดผลรวมของการทำงานเป็นศูนย์ในบางจุด IP เคลื่อนไปทางขวาล่าง,และอ่านตัวละครอื่นเพื่อตรวจสอบว่าเราถึง EOF หรือไม่ หากไม่ใช่ค่าจะเป็นค่าบวกและ IP จะหันไปทางตะวันตก@และโปรแกรมจะหยุดทำงาน ถ้าเราทำ EOF เข้าถึง IP ที่หันทิศตะวันออกและพิมพ์ด้วย-1 !IP จะเวิร์มไปทางซ้ายล่าง@ผ่านเส้นทางแปลก ๆ เพื่อยุติโปรแกรม


0

Python ขนาด 82 ไบต์

lambda l:len(l)==sum(l)+1 and not any(list(l[x]>=len(l)-x for x in range(len(l))))

ต้องการกรณีทดสอบเพิ่มเติม


คุณไม่จำเป็นต้องร่ายด้วยlistถ้านี่เป็น Python 2 อย่างน้อยและโดยการจัดเรียงใหม่และกลับเงื่อนไขที่สองคุณสามารถรับได้ที่ 70 ไบต์:lambda l:all(l[x]<len(l)-x for x in range(len(l)))and len(l)==sum(l)+1
Kade

^ ในความสัมพันธ์กับสิ่งนี้คุณสามารถเปลี่ยนเนื้อหาของallการเป็นx<len(l)-y for y,x in enumerate(l)เพื่อบันทึกอีก 2 ไบต์เพื่อรับเป็น 68
Kade

ฉันไม่ได้เล่นกอล์ฟต่อไปในขณะนี้เพราะฉันไม่คิดว่ามันจะเป็นทางออกที่ถูกต้อง ขอบคุณสำหรับเคล็ดลับ
Sparr

0

Pyth, 13 ไบต์

qxsM._tMQ_1tl

เราเริ่มต้นด้วยการคำนวณค่าที่เติมเต็มของต้นไม้ในทุกจุดในการแสดงค่าอินพุต ส่วนหนึ่งของความคิดนั้นมาจาก Martin Ender เป็นส่วนใหญ่ขอบคุณเขาsM._tMQ

เมื่อเรามีรายการนี้เราจะตรวจสอบว่าดัชนีแรกที่มี-1( x..._1) คือความยาวของอินพุตลบหนึ่ง ( q...tl(Q))

ไม่เชื่อว่ามันใช้งานได้? ลองด้วยตัวคุณเอง!

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