ซานต้าเข้าห้องใต้ดินได้เมื่อไหร่? (AOC วัน 1)


20

ฉันทำซ้ำส่วนที่สองของวันแรกของ Advent of Code โดยได้รับอนุญาตจากผู้สร้าง

ซานต้ากำลังพยายามส่งของขวัญในอาคารอพาร์ตเมนต์ขนาดใหญ่ แต่เขาไม่สามารถหาชั้นที่เหมาะสมได้ทิศทางที่เขาได้มานั้นค่อนข้างสับสน เขาเริ่มที่ชั้นล่าง (ชั้น 0) จากนั้นทำตามคำแนะนำทีละตัวอักษร

วงเล็บเปิด(หมายความว่าเขาควรขึ้นไปหนึ่งชั้นและวงเล็บปิด)หมายความว่าเขาควรลงหนึ่งชั้น

อาคารอพาร์ตเมนต์สูงมากและชั้นใต้ดินลึกมาก เขาจะไม่พบชั้นบนหรือชั้นล่าง

ให้ชุดคำสั่งค้นหาตำแหน่งของอักขระตัวแรกที่ทำให้เขาเข้าไปในห้องใต้ดิน (ชั้น -1)

เป็นตัวอย่าง:

การป้อนข้อมูล)ทำให้เขาเข้าไปในห้องใต้ดินที่ตำแหน่งตัวละคร 1

การป้อนข้อมูล()())ทำให้เขาเข้าไปในห้องใต้ดินที่ตำแหน่งตัวละคร 5

อินพุตแบบยาวถูกให้ที่นี่ซึ่งควรให้ผลลัพธ์โซลูชัน 1797

นี่คือรหัสกอล์ฟดังนั้นทางออกที่สั้นที่สุดชนะ!


เราต้องใช้ตัวอักษรที่แน่นอนเหล่านั้นหรือไม่
บลู

1
@muddyfish ในความท้าทายดั้งเดิมมีการป้อนข้อมูลในรูปแบบที่เฉพาะเจาะจงและบ่อยครั้งที่ส่วนสำคัญของความท้าทายคือการแยกวิเคราะห์อินพุต ในขณะที่ฉันไม่ต้องการให้สิ่งนี้กลายเป็น "ปัญหากิ้งก่า" ฉันคิดว่าจิตวิญญาณของต้นฉบับคือการป้อนข้อมูลควรเป็นสตริงของวงเล็บ ฉันรู้ว่านี่เป็นสิทธิพิเศษสำหรับบางภาษาในบางภาษา แต่ฉันจะขอให้ผู้ลงคะแนนพิจารณาเรื่องนี้เมื่อตัดสินรางวัล upvotes
ซิมมอนส์

มีความเกี่ยวข้องอย่างใกล้ชิดกับเลขฐานสอง Parenthifiable ... ฉันไม่ได้รู้สึกว่ามันเป็นล่อลวงมากนักดังนั้นฉันจะแสดงความคิดเห็นแทน
AdmBorkBork

@ TimmyD ฉันเห็นสิ่งที่คุณหมายถึง แต่ฉันรู้สึกว่าคำถามนี้แตกต่างกันพอที่คำตอบการแข่งขันจะไม่สามารถดึงจากคำถามที่มากเกินไป!
ซิมมอนส์

1
ฉันพยายามที่จะแก้ปัญหานี้ใน SMBF (โดยพื้นฐาน BF) และภาษานี้ใช้เพื่อแก้จุดบกพร่อง ... เอ่อ
mbomb007

คำตอบ:


17

เยลลี่, 8 7 ไบต์

O-*+\i-

ขอบคุณ @ Sp3000 สำหรับการตีกอล์ฟ 1 ไบต์!

ลองออนไลน์!

มันทำงานอย่างไร

O-*+\i-    Main link. Input: s (string)

O          Ordinal; replace each character with its code point.
           This maps "()" to [48, 49].
 -*        Apply x -> (-1) ** x.
           This maps [48, 49] to [1, -1].
   +\      Compute the cumulative sum, i.e., the list of partial sums.
     i-    Find the first index of -1.

16

Python 2, 44 ไบต์

try:input()
except Exception,e:print e[1][2]

การแก้ปัญหาที่ฉลาดถูกพบโดย hallvabo, xsot, mitchs และ whatisgolf ในปัญหานี้บนโกลาหลกอล์ฟ หากคุณต้องการโพสต์แทนฉันจะลบสิ่งนี้

เคล็ดลับคือการให้โปรแกรมแยกวิเคราะห์ Python ทำงาน ฟังก์ชั่นinput()พยายามที่จะประเมินสตริงการป้อนและโยนข้อผิดพลาดใน paren แรกที่ไม่ตรงกัน ข้อผิดพลาดนี้เมื่อถูกจับมีรูปแบบ

SyntaxError('unexpected EOF while parsing', ('<string>', 1, 1, ')'))

ซึ่งรวมถึงหมายเลขอักขระที่เกิดข้อผิดพลาด


7

Python, 79 77 ไบต์

lambda m:[sum([2*(z<')')-1for z in m][:g])for g in range(len(m)+1)].index(-1)

อาจมีวิธีที่ดีกว่าในการทำเช่นนี้ แต่ฉันไม่มีความคิด นี่เป็นโพสต์แรกของฉันเกี่ยวกับ codegolf

ขอบคุณ @Erwan สำหรับการเล่นกอล์ฟ 2 ไบต์


ยินดีต้อนรับสู่เว็บไซต์! นี่เป็นโพสต์แรกที่ดีมาก :)
Alex A.

คุณสามารถแทนที่[0:g]โดย[:g]
Erwan

และการเปลี่ยนนี้บันทึก 1 ไบต์ผมคิดว่า-2*ord(z)+81โดย2*(z<')')-1
Erwan

5

Python 3, 59

บันทึกแล้ว 3 ไบต์ขอบคุณ grc

ฉันไม่ชอบทำดัชนีสตริงด้วยตนเองใน Python รู้สึกผิดปกติ

def f(x):
 c=q=0
 while-~c:c+=1-(x[q]>'(')*2;q+=1
 return q

5

C, 55 ไบต์

g;main(f){for(;f;g++)f+=81-getchar()*2;printf("%d",g);}

ลองมันนี่

แก้ไข: ไม่แน่ใจว่าทำไมฉันทิ้งตัวแปรที่ไม่ได้ใช้ในนั้น ...


5

CJam, 10 ไบต์

0l'_*:~1#)

หรือ

0l'_*~]1#)

หรือ (ให้เครดิตกับเดนนิส)

Wl+'_*:~1#

ทดสอบที่นี่

คำอธิบาย

ตามที่ซิมมอนส์กล่าวไว้แล้ว()เป็นทางเลือกที่โชคดีสำหรับ CJam เนื่องจากเป็นตัวดำเนินการลด / เพิ่มตามลำดับ นั่นหมายความว่าถ้าเราเริ่มต้นจากศูนย์เรากำลังมองหาขั้นตอนที่ซานต้ามาถึงชั้น 1

0   e# Push 0, the initial floor.
l   e# Read input.
'_* e# Riffle the input string with underscores, which duplicate the top of the stack.
:~  e# Evaluate each character, using a map which wraps the result in an array.
1#  e# Find the position of the first 1.
)   e# Increment because we're looking for a one-based index.

4

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

+(+"#(!@
:  :
%2_,

ลองออนไลน์! คำตอบนี้เป็นผลมาจากการร่วมมือกับ @ MartinBüttner

คำอธิบาย

ไพรเมอร์ Labyrinth ปกติ (ฉันพูดว่า "ปกติ" แต่ฉันเขียนใหม่นี้ทุกครั้ง):

  • Labyrinth เป็นภาษา 2D ตามสแต็กโดยเริ่มต้นจากถ่านตัวแรกที่ถูกต้อง (ที่นี่ด้านซ้ายบน) ที่แต่ละจุดเชื่อมต่อที่มีเส้นทางที่เป็นไปได้ตั้งแต่สองเส้นทางขึ้นไปเพื่อให้ตัวชี้คำแนะนำใช้งานด้านบนของสแต็กจะถูกตรวจสอบเพื่อกำหนดตำแหน่งที่จะไปต่อไป ลบคือเลี้ยวซ้ายศูนย์จะไปข้างหน้าและบวกจะเลี้ยวขวา
  • สแต็กไม่มีก้นลึกและเต็มไปด้วยเลขศูนย์ดังนั้นการ popping จากสแต็กที่ว่างเปล่าไม่ใช่ข้อผิดพลาด
  • ตัวเลขในรหัสที่มาไม่ได้ผลักดันจำนวนที่สอดคล้องกัน - n*10 + <digit>แทนพวกเขาปรากฏด้านบนของสแต็คและผลักดัน สิ่งนี้ช่วยให้ง่ายต่อการสร้างจำนวนมาก ในการเริ่มหมายเลขใหม่ให้ใช้_ซึ่งจะเพิ่มจำนวนศูนย์

รหัสนี้ค่อนข้างแปลกตั้งแต่สำหรับการเล่นกอล์ฟวงหลักจะรวมสองงานเข้าด้วยกัน สำหรับครึ่งแรกของรอบแรกนี่คือสิ่งที่เกิดขึ้น:

+(+             Add two zeroes, decrement, add with zero
                This leaves -1 on the stack
"               NOP at a junction. -1 is negative so we try to turn left, fail, and
                turn right instead.
:               Duplicate -1

ตอนนี้สแต็กถูกกำหนดค่าเริ่มต้นด้วย -1 ที่ด้านบนการประมวลผลที่แท้จริงสามารถเริ่มต้นได้ นี่คือสิ่งที่วงหลักทำ

,               Read a byte of input
_2%             Take modulo 2.
:+              Duplicate and add, i.e. double
(               Decrement
                This maps "(" -> -1, ")" -> 1
+               Add to running total
"               NOP at a junction. Go forward if zero, otherwise turn right.
:               Duplicate the top of the stack

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

#               Push stack depth
(               Decrement
!               Output as num
@               Terminate

3

Oracle SQL 11.2, 160 159 ไบต์

SELECT MIN(l)FROM(SELECT l,SUM(m)OVER(ORDER BY l)p FROM(SELECT LEVEL l,DECODE(SUBSTR(:1,LEVEL,1),'(',1,-1)m FROM DUAL CONNECT BY LEVEL<=LENGTH(:1)))WHERE p=-1;

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

SELECT MIN(l) -- Keep the min level
FROM(
  SELECT l,SUM(m)OVER(ORDER BY l)p -- Sum the () up to the current row
  FROM(
    SELECT LEVEL l,DECODE(SUBSTR(:1,LEVEL,1),'(',1,-1)m -- ( equal 1 and ) equal -1 
    FROM DUAL 
    CONNECT BY LEVEL<= LENGTH(:1)
  )
)
WHERE p=-1 -- Keep the rows where the () sum is equal to -1

3

จอประสาทตา22 21

! M` ^ ((\ ()? |. (<- 2>)) +

ลองออนไลน์หรือทดลองใช้กรณีทดสอบขนาดใหญ่ (URL มีขนาดใหญ่สำหรับกรณีทดสอบขนาดใหญ่แจ้งให้เราทราบหากแบ่งให้คุณดูเหมือนว่าตกลงในโครม)

บันทึก 1 ไบต์ขอบคุณ Martin!

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

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


ซานตาใช้ปืนพอร์ทัลของเขา
mbomb007

3

Grep + AWK, 51 ไบต์

grep -o .|awk '/\(/{s++}/)/{s--}s<0{print NR;exit}'

grepคำสั่งสถานที่ตัวละครแต่ละตัวในบรรทัดใหม่


3

Pyth, 13 ไบต์

f!hsm^_1Cd<zT

คำอธิบาย

              - autoassign z = input()
f             - First where V returns Truthy.
          <zT -     z[:T]
    m         -    [V for d in ^]
        Cd    -     ord(d)
     ^_1      -      -1**^
   s          -   sum(^)
 !h           -  not (^+1)

ลองที่นี่

อัลกอริทึมเก่า 15 ไบต์

f!h-/J<zT\(/J\)

คำอธิบาย:

                - autoassign z = input()
f               - First where V returns Truthy.
      <zT       -      z[:T]
     J          -     autoassign J = ^
    /    \(     -    ^.count("(")
           /J\) -    J.count(")")
   -            -   ^-^
 !h             -  not (^+1)

ลองที่นี่

หรือหากได้รับอนุญาตให้ใช้ตัวอักษรอื่นนอกเหนือจาก(และ), 9 ไบต์ (การย้ายการประมวลผลล่วงหน้าเป็นอินพุต)

f!.v+<zT1

คำอธิบาย

          - autoassign z = input()
f         - First where V returns Truthy.
     <zT  -     z[:T]
    +   1 -    ^+"1"
  .v      -   eval(^)
 !        -  not ^

ลองที่นี่


3

JavaScript (ES6), 58 ไบต์

f=(s,t=s)=>s<')'?f(s.replace('()',''),t):t.length-s.length+1

ทำงานโดยการลบซ้ำคู่จับคู่จนถึงตัวอักษรตัวแรกเป็น() )คำเตือน: อย่าลองนี้ในสายที่ไม่ได้มีมากพอที่)s ตัวอย่าง:

((()())()))
((())()))
(()()))
(()))
())
)

ณ จุดนี้จะเห็นว่ามีการลบอักขระทั้งหมด 12 ตัวดังนั้นคำตอบคือ 13


คุณสามารถใส่ความคิดเห็นนั้นลงในคำตอบของคุณแทน
mbomb007

3

MATL , 12 11 ไบต์

1 ไบต์ถูกบันทึกโดยใช้แนวคิดการคำนวณของเดนนิส -1 เพิ่มเป็นสตริงอินพุต

1_j^Ys0<f1)

ลองออนไลน์!

1_         % number -1
j          % take string input
^          % element-wise power. This transforms '('  to 1 and ')' to -1
Ys         % cumulative sum
0<         % true for negative values
f          % find all such values 
1)         % pick first. Implicit display

2

CJam, 12 10 ไบต์

0q{~_}%1#)

ลองที่นี่

บันทึกสองไบต์ด้วย Martin

คำอธิบาย:

0              Load 0 onto the stack
 q             Load input onto the stack without evaluating
  {  }       Code block
   ~_          Evaluate the next command and duplicate the top stack element. The format of the question is good for CJam and Golfscript since ) and ( are increment and decrement operators (though the wrong way round).
        %      Map this code block over the string. This yields an array of Santa's floor positions
         1#   Find the first instance of a 1, since decrement and increment are swapped
           )  Fix the off-by-1 error caused by zero-indexing


2

Perl, 34 + 1 = 35 ไบต์

$.+=s+.+++s+\)++while")"gt$_;$_=$.

ขอบคุณเดนนิสสำหรับเคล็ดลับ

วิ่งด้วย-pธง มันทำงานได้ใน Perl 5.10 แต่รุ่นที่ใหม่กว่าต้องการพื้นที่ว่างที่นี่:++ while

รุ่นที่เก่ากว่าที่ไม่ได้รับการดัดแปลง:

$_ = <>;                # get a line of input
while ($_ lt ')') {     # while it begins with a (
    s/.//;              # remove the first (
    s/\)//;             # remove the first )
    $i += 2;            # increase index by 2
}
print $i + 1;           # print the position

2

Python ขนาด 44 ไบต์

f=lambda s,i=1:i and-~f(s[1:],i-1+2*(s<')'))

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


2

Javascript, 57 ไบต์

p=>{c=0;for(i in p){c+=p[i]==')'?-1:1;if(c<0)return+i+1}}

ค่อนข้างเรียบง่ายเพียงวนซ้ำอินพุต, incs ถ้า '(' ตัดสินใจถ้า ')' ส่งคืนค่าลบแรก



1

C, 73 ไบต์

main(f,c){f=c=0;for(;f!=-1;c++){f+=1-((getchar()&1)<<1);}printf("%d",c);}

คาดว่าอินพุตใน STDIN; ไม่มีอักขระอื่นนอกจาก(และ)อาจปรากฏในอินพุต (อย่างน้อยก็จนกว่าเราจะได้คำตอบ) ข้อมูลที่ป้อนต้องเป็น ASCII

ส่งคำตอบใน STDOUT

ใช้ความแตกต่าง 1 บิตระหว่าง ASCII สำหรับและ()

/* old-style arguments, implicitly int */
main(x, f)
{
    /* c is our character counter, f is the floor*/
    c = f = 0;
    /* increase c while f is not -1 */
    for (;f != -1; c++) {
        /* use difference in LSB to add one for (, subtract one for ) */
        f += 1-((getchar()&1)<<1);
    }
    /* answer */
    printf("%d", c);
}

เวอร์ชันที่มีรูปแบบสวยงาม:


คุณสามารถย้ายไปf=c=0สู่การเริ่มต้นของการวนซ้ำfor(f=c=0;f!=...เพื่อบันทึกไบต์ได้หรือไม่?
AdmBorkBork

@ TimmyD ดีกว่าที่จะทำให้พวกเขาเป็นสากลเพื่อให้พวกเขากำลังเริ่มต้นอัตโนมัติ
Cole Cameron

1

PowerShell, 75 65 62 ไบต์

[char[]]$args[0]|%{$c+=(1,-1)[$_%40];$d++;if($c-lt0){$d;exit}}

ใช้เทคนิคที่คล้ายกันกับเลขฐานสองแบบ Parenthifiableเพื่อวนซ้ำอักขระที่ป้อนทั้งหมดทำให้การใช้งาน$cของ+1แต่ละคน(และ-1แต่ละครั้ง)นั้นทดสอบว่าเราตีเชิงลบหรือไม่ (เช่นเราอยู่ในห้องใต้ดิน)

แก้ไข - บันทึก 10 ไบต์ด้วยการวนซ้ำอักขระจริงแทนที่จะเป็นดัชนี
แก้ไข 2 - บันทึก 3 ไบต์เพิ่มเติมโดยการสลับการตรวจสอบความเท่าเทียมกันสำหรับโมดูโล


1

Mathematica, 62 55 ไบต์

Position[Accumulate[(-1)^ToCharacterCode@#],-1][[1,1]]&

ชื่อฟังก์ชันยาวทั้งหมด! ทำงานคล้ายกับคำตอบ CJam ของ Simmons


1

Befunge 25 ไบต์

เอาท์พุท unary สิ่งนี้จะเริ่มคุณที่ชั้นหนึ่งและจะไปจนถึง 0

1<\1_v#:+-*2%2~
:#._@>$1>

1

แร็กเก็ต (102)

(λ(s)(let l((c 0)(b 0)(s(string->list s)))(if(> 0 b)c(l(+ 1 c)((if(eqv?(car s)#\()+ -)b 1)(cdr s)))))

Ungolfed

(λ (input)
  (let loop ((count 0) (balance 0) (chars (string->list input)))
    (if (> 0 balance)
        count
        (loop (+ 1 count)
              ((if (eqv? (car chars) #\() + -) balance 1)
              (cdr chars)))))

1

APL, 18 ตัวอักษร

{1⍳⍨¯1=+\¯1*')'=⍵}

เป็นภาษาอังกฤษ:

  • ¯1*')'=⍵: -1 โดยที่ input = ")", 1 เป็นอย่างอื่น;
  • +\: ผลรวมสะสม;
  • 1⍳⍨¯1=: หาดัชนีของ -1 แรก

1

Lua, 92 89 87 Bytes

มันใช้เวลาในอาร์กิวเมนต์บรรทัดคำสั่ง

แก้ไข: บันทึก 3 ไบต์

แก้ไข: บันทึก 2 ไบต์และแก้ไขข้อผิดพลาดที่อาจเกิดขึ้นในกรณีที่ขอบขณะนี้มันส่งออกผ่านรหัสทางออกของมัน

r=0i=0(...):gsub(".",function(c)i=i+1r=r+(c==")"and-1or 1)if r<0then os.exit(i)end end)

Ungolfed

r,i=0,0                     -- set r (the actual floor), and i(the character count)
(...):gsub(".",function(c) -- apply an anonymous functions on each character of the input
  i,r=i+1,                  -- increment i
      r+(c==")"and -1 or 1) -- decrement r if c==")", increment it otherwise
  if r<0 then os.exit(i)end -- if r==-1, exit and output the current index
end)

1

k / kona , 23 21 ไบต์

บันทึก 2 ไบต์โดยการลบวงเล็บที่ไม่จำเป็นออก

{1+(+\1 -1"()"?x)?-1}

การใช้งาน:

k){1+(+\1 -1"()"?x)?-1} "())"
3

0

Perl, 40 + 1 = 41 ไบต์

$y++,($i+=/\(/*2-1)<0&&last for/./g;$_=$y

ต้องการ-pธง:

$ perl -pe'$y++,($i+=/\(/*2-1)<0&&last for/./g;$_=$y' <<< '()())'
5
$ perl -pe'$y++,($i+=/\(/*2-1)<0&&last for/./g;$_=$y' 1797.txt
1797

ถือว่าอินพุตที่ถูกต้อง

มันทำงานอย่างไร:

                                           # -p read line by line into $_ and auto prints at the end
        $y++,                              # Counter for steps taken
             ($i+=/\(/*2-1) < 0            # The match /\(/ will give 1 or 0 in a numeric context 1 for `(` and 0 for anything else
                                           # times it by 2 and subtracting -1 will yield 1 or -1
                               && last     # End the iteration if $i < 0
for/./g;                                   # Iterate over each items in the input
                                      $_=$y# Print the output

0

Javascript (ES6), 68 67 ไบต์

(s,r,f=0)=>s.split``.map((l,i)=>(f+=l=='('?1:-1,f<0?r=r||++i:0))&&r

รับอินพุตเป็นอาร์กิวเมนต์แรก

คำอธิบาย

(s, r, f=0)                                  //Gets string, declares r and f to equal undefined and 0
         =>
            s.split``                        //Splits string into character array
            .map(                            //Loops over array
                 (l, i)=>(
                         f +=                //Increment f
                         l=='(' ? 1 : -1,    //By either 1 or -1 depending on character
                         f<0 ?               //If the floor is less than 0
                         r=r||++i            //And is first time below, r equals index (+1 to make it '1 indexed not 0')
                         : 0)
                         &&r                   //Return index

0

Python (3.5), 78 71 62 ไบต์

โซลูชันแบบเรียกซ้ำ

f=lambda s,p=0,v=0:p if v<0else f(s[1:],p+1,v+2*(s[0]<')')-1) 

มันคล้ายกับโซลูชันนี้สำหรับมินิกอล์ฟ

เราสามารถสมมติว่าซานต้าเข้าถึงชั้นใต้ดินได้เสมอ

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