Kapan Santa memasuki ruang bawah tanah? (AOC Hari 1)

20

Saya mereproduksi bagian kedua dari hari pertama Advent of Code, dengan izin dari pencipta.

Santa sedang berusaha mengirimkan hadiah di sebuah gedung apartemen besar, tetapi ia tidak dapat menemukan lantai yang tepat - arah yang ia dapatkan agak membingungkan. Dia mulai di lantai dasar (lantai 0) dan kemudian mengikuti instruksi satu karakter pada suatu waktu.

Tanda kurung pembuka (,, berarti ia harus naik satu lantai, dan tanda kurung tutup ),, berarti ia harus turun satu lantai.

Bangunan apartemen sangat tinggi, dan ruang bawah tanahnya sangat dalam; dia tidak akan pernah menemukan lantai atas atau bawah.

Diberikan seperangkat instruksi, cari posisi karakter pertama yang menyebabkan dia memasuki ruang bawah tanah (lantai -1).

Sebagai contoh:

masukan )menyebabkan dia memasuki ruang bawah tanah pada posisi karakter 1.

masukan ()())menyebabkan dia memasuki ruang bawah tanah pada posisi karakter 5.

Masukan panjang diberikan di sini yang akan menghasilkan solusi 1797.

Ini kode golf, jadi solusi terpendek menang!

A Simmons
sumber
Apakah kita harus menggunakan karakter itu?
Biru
1
@muddyfish Dalam tantangan asli input diberikan dalam bentuk tertentu dan seringkali bagian kunci dari tantangan adalah mengurai input; sementara saya tidak ingin ini menjadi "masalah bunglon" saya pikir semangat aslinya adalah bahwa input harus berupa kurung. Saya menyadari ini memang mengistimewakan beberapa bahasa daripada yang lain, tetapi saya akan meminta pemilih untuk mempertimbangkan hal ini ketika memberi penghargaan untuk solusi.
A Simmons
Sangat terkait erat dengan angka biner yang dapat dipastikan ... Saya tidak merasa cukup kuat bahwa itu adalah penipuan, jadi saya hanya akan memberikan komentar saja.
AdmBorkBork
@TimmyD Saya mengerti maksud Anda, tetapi saya merasa pertanyaan ini cukup berbeda sehingga jawaban kompetitif tidak akan dapat menarik terlalu banyak dari pertanyaan itu!
A Simmons
1
Saya mencoba untuk menyelesaikan ini di SMBF (pada dasarnya BF), dan bahasa ini SUCKS untuk debug ... ugh.
mbomb007

Jawaban:

17

Jelly, 8 7 byte

O-*+\i-

Terima kasih kepada @ Sp3000 untuk bermain golf 1 byte!

Cobalah online!

Bagaimana itu bekerja

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.
Dennis
sumber
16

Python 2, 44 byte

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

Solusi cerdas ini ditemukan oleh hallvabo, xsot, mitchs, dan whatisgolf pada masalah ini di golf Anarchy . Jika ada di antara Anda yang ingin mempostingnya, saya akan menghapus ini.

Triknya adalah membiarkan pengurai Python melakukan pekerjaan. Fungsi input()mencoba mengevaluasi string input, dan melempar kesalahan pada paren pertama yang tidak cocok. Kesalahan ini, ketika tertangkap, memiliki bentuk

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

yang mencakup nomor karakter tempat kesalahan terjadi.

Tidak
sumber
7

Python, 79 77 Bytes

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

Mungkin ada cara yang lebih baik untuk melakukan ini, tetapi saya kehabisan ide. Juga ini adalah posting pertama saya tentang codegolf.

Terima kasih kepada @Erwan. untuk bermain golf 2 byte.

drobilc
sumber
Selamat datang di situs ini! Ini adalah posting pertama yang sangat bagus. :)
Alex A.
Anda dapat menggantinya [0:g]dengan[:g]
Erwan
dan penggantian ini menghemat 1 byte saya pikir -2*ord(z)+81oleh2*(z<')')-1
Erwan
5

Python 3, 59

Disimpan 3 byte berkat grc.

Saya sangat tidak suka melakukan pengindeksan string manual dengan Python. Rasanya sangat salah.

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

C, 55 byte

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

Coba di sini .

Sunting: Tidak yakin mengapa saya meninggalkan variabel yang tidak digunakan di sana ...

Cole Cameron
sumber
5

CJam, 10 byte

0l'_*:~1#)

atau

0l'_*~]1#)

atau (kredit untuk Dennis)

Wl+'_*:~1#

Uji di sini.

Penjelasan

Seperti yang sudah dicatat oleh A Simmons, ()adalah pilihan yang beruntung bagi CJam karena mereka adalah operator penurunan / kenaikan, masing-masing. Itu berarti jika kita mulai dari nol, kita sedang mencari langkah di mana Santa mencapai lantai 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.
Martin Ender
sumber
4

Labirin , 18 byte

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

Cobalah online!Jawaban ini adalah hasil kolaborasi dengan @ MartinBüttner.

Penjelasan

Primer Labyrinth yang biasa (saya katakan "biasa", tapi saya sebenarnya menulis ulang ini setiap waktu):

  • Labyrinth adalah bahasa 2D berbasis stack, dengan eksekusi dimulai dari karakter pertama yang valid (di sini bagian kiri atas). Di setiap persimpangan, di mana ada dua atau lebih jalur yang mungkin untuk diambil oleh penunjuk instruksi, bagian atas tumpukan diperiksa untuk menentukan ke mana harus pergi berikutnya. Negatif belok kiri, nol maju dan positif belok kanan.
  • Tumpukan tidak berdasar dan diisi dengan nol, sehingga muncul dari tumpukan kosong bukanlah kesalahan.
  • Digit dalam kode sumber tidak mendorong nomor yang sesuai - sebaliknya, mereka mengeluarkan bagian atas tumpukan dan mendorong n*10 + <digit>. Ini memungkinkan penumpukan yang mudah dalam jumlah besar. Untuk memulai nomor baru, gunakan _, yang mendorong nol.

Kode ini agak aneh karena, untuk tujuan bermain golf, loop utama menggabungkan dua tugas menjadi satu. Untuk paruh pertama dari operan pertama, inilah yang terjadi:

+(+             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

Sekarang stack telah diinisialisasi dengan -1 di atas, pemrosesan yang sebenarnya dapat dimulai. Inilah yang dilakukan loop utama.

,               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

Duplikat terakhir menambahkan elemen ke tumpukan untuk setiap iterasi yang kami lakukan. Ini penting karena, ketika kita mencapai nol dan maju di NOP, kita lakukan:

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

Oracle SQL 11.2, 160 159 byte

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;

Tidak bermain golf

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
Jeto
sumber
3

Retina ,22 21

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

Cobalah online atau coba test case besar. (URL besar untuk test case besar, beri tahu saya jika rusak untuk Anda, sepertinya OK di chrome.)

1 byte disimpan berkat Martin!

Kami mencocokkan set kurung pertama yang seimbang dan mengekstraknya, lalu kami menghitung berapa kali string kosong akan cocok dengan hasil itu. Saya tidak yakin apakah ini cara terbaik untuk melakukan ini di Retina, terutama jika mode PCRE membuatnya lebih pendek, tetapi menggunakan$#_ penggantian tampaknya lebih lama karena dimatikan oleh satu kesalahan dan masalah memiliki lebih dari satu pertandingan.

Algoritma ini menyebabkan perilaku aneh untuk input yang tidak valid, pada dasarnya mengasumsikan bahwa jika Santa tidak berhasil mencapai ruang bawah tanah, ia secara misterius melakukan teleportasi di sana setelah pergerakan lainnya.

FryAmTheEggman
sumber
3

Grep + AWK, 51 Bytes

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

The grepperintah menempatkan masing-masing karakter pada baris baru.

Robert Benson
sumber
3

Pyth, 13 byte

f!hsm^_1Cd<zT

Penjelasan

              - 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)

Coba di sini

Algoritma lama, 15 byte

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

Penjelasan:

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

Coba di sini

Atau jika diizinkan menggunakan karakter selain (dan ), 9 byte (memindahkan pra-pemrosesan ke input)

f!.v+<zT1

Penjelasan

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

Coba di sini

Biru
sumber
3

JavaScript (ES6), 58 byte

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

Bekerja dengan menghapus pasangan yang cocok secara rekursif ()hingga karakter pertama adalah a ). Peringatan: Jangan coba ini pada string yang tidak memiliki cukup ). Contoh:

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

Pada titik ini terlihat bahwa 12 karakter telah dihapus total sehingga jawabannya adalah 13.

Neil
sumber
Anda bisa memasukkan komentar itu sebagai jawaban.
mbomb007
3

MATL , 12 11 byte

1 byte disimpan menggunakan ide komputasi Dennis -1 yang diangkat ke string input

1_j^Ys0<f1)

Cobalah online!

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
Luis Mendo
sumber
2

CJam, 12 10 Bytes

0q{~_}%1#)

Coba di sini.

Dua byte disimpan berkat Martin.

Penjelasan:

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
A Simmons
sumber
2

Javascript, 117 byte

o=f=0;i=prompt().split('');for(c in i){switch (i[c]){case '(':f++;break;case ')':f--;if(f<0){alert(o+1);i=[];}}o++;}

Abaikan karakter lain. Penggunaan promptdan alert.

Solomon Ucko
sumber
2

Perl, 34 + 1 = 35 byte

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

Terima kasih untuk Dennis untuk beberapa tips.

Jalankan dengan -pbendera. Ini berfungsi di Perl 5.10, tetapi versi yang lebih baru membutuhkan ruang di sini:++ while

Versi yang lebih tua, tidak diserang:

$_ = <>;                # 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
grc
sumber
2

Python, 44 byte

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

Lantai idimulai pada 1sehingga kami mengakhiri imenjadi nilai falsey 0. Jika tidak dihentikan, tambahkan satu secara rekursif untuk menghasilkan dengan karakter pertama dihapus dan nomor lantai diperbarui berdasarkan karakter itu.

Tidak
sumber
2

Javascript, 57 byte

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

Cukup sederhana, hanya mengulangi input, incs if '(' decs if ')'. Pengembalian negatif pertama.

SethWhite
sumber
2

Ruby, 47 byte

Fungsi anonim.

->s{i,l=-1,0;l+=s[i+=1]>?(?-1:1 while l>-1;i+1}
Nilai Tinta
sumber
1

C, 73 byte

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

Mengharapkan masukan pada STDIN; tidak ada karakter selain (dan )dapat muncul dalam input (setidaknya sampai kami telah mencapai jawabannya). Masukan harus ASCII.

Memancarkan jawaban pada STDOUT.

Menggunakan perbedaan 1-bit antara ASCII untuk (dan ).

/* 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);
}

Versi yang diformat dengan baik:

David Morris
sumber
Bisakah Anda memindahkan f=c=0ke inisialisasi loop for(f=c=0;f!=...untuk menyimpan byte?
AdmBorkBork
@TimmyD lebih baik untuk menjadikannya global sehingga otomatis diinisialisasi.
Cole Cameron
1

PowerShell, 75 65 62 byte

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

Menggunakan teknik yang sama seperti pada bilangan biner Parenthifiable untuk mengulangi semua karakter input, menjaga $counter berjalan +1untuk masing-masing (dan -1untuk masing-masing ), kemudian menguji apakah kami telah mencapai negatif (yaitu, kami berada di ruang bawah tanah).

Edit - disimpan 10 byte dengan mengulangi karakter yang sebenarnya daripada indeksnya.
Edit 2 - menyimpan 3 byte tambahan dengan menukar cek kesetaraan untuk modulo sehingga casting secara implisit

AdmBorkBork
sumber
1

Mathematica, 62 55 byte

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

Semua nama fungsi panjang! Bekerja mirip dengan jawaban SimJons CJam.

LegionMammal978
sumber
1

Dibalik 25 byte

Keluaran dalam unary. Ini mulai Anda di lantai satu, dan akan pergi sampai 0.

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

Racket (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)))))

Tidak disatukan

(λ (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)))))
Sylwester
sumber
1

APL, 18 karakter

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

Dalam Bahasa Inggris:

  • ¯1*')'=⍵: -1 di mana input = ")", 1 sebaliknya;
  • +\: running sum;
  • 1⍳⍨¯1=: cari indeks -1 pertama.
lstefano
sumber
1

Lua, 92 89 87 Bytes

Dibutuhkan argumen baris perintah.

Sunting: Disimpan 3 Bytes

Sunting: Disimpan 2 byte, dan dikoreksi bug yang bisa terjadi pada kasus tepi, sekarang output melalui kode keluarnya

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

Tidak disatukan

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)
Katenkyo
sumber
1

k / kona , 23 21 bytes

2 byte disimpan dengan menghapus tanda kurung yang tidak perlu.

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

Pemakaian:

k){1+(+\1 -1"()"?x)?-1} "())"
3
Simon Major
sumber
0

Perl, 40 + 1 = 41 byte

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

Membutuhkan -pbendera:

$ 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

Mengasumsikan input yang valid.

Bagaimana itu bekerja:

                                           # -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
andlrc
sumber
0

Javascript (ES6), 68 67 byte

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

Mengambil input sebagai argumen pertama

Penjelasan

(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
reubn
sumber
0

Python (3.5), 78 71 62 byte

solusi rekursif

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

ini mirip dengan solusi ini untuk golf mini

kita dapat mengasumsikan santa selalu mencapai ruang bawah tanah

Erwan
sumber