Phân tích định dạng từ điển Bookworm


42

Gần đây tôi đã đắm chìm trong một số nỗi nhớ dưới dạng Bookworm Deluxe:

Trong trường hợp bạn chưa từng thấy nó trước đây, thì đây là một trò chơi chữ với mục tiêu là kết nối các ô liền kề để tạo thành các từ. Để xác định xem một chuỗi có phải là một từ hợp lệ hay không, nó sẽ kiểm tra nó dựa vào từ điển bên trong của nó, được lưu trữ ở định dạng nén trông như thế này:

aa
2h
3ed
ing
s
2l
3iis
s
2rdvark
8s
4wolf
7ves

Các quy tắc để giải nén từ điển rất đơn giản:

  1. Đọc số ở đầu dòng và sao chép nhiều ký tự từ đầu của từ trước đó. (Nếu không có số, hãy sao chép nhiều ký tự như bạn đã làm lần trước.)

  2. Nối các chữ cái sau vào từ.

Vì vậy, từ đầu tiên của chúng tôi là aa, theo sau 2h, có nghĩa là "sao chép hai chữ cái đầu tiên aavà nối thêm h", hình thành aah. Sau đó 3edtrở thành aahedvà vì dòng tiếp theo không có số, chúng tôi sao chép lại 3 ký tự để tạo thành aahing. Quá trình này tiếp tục trong suốt phần còn lại của từ điển. Các từ kết quả từ đầu vào mẫu nhỏ là:

aa
aah
aahed
aahing
aahs
aal
aaliis
aals
aardvark
aardvarks
aardwolf
aardwolves

Thách thức của bạn là thực hiện việc giải nén này trong càng ít byte càng tốt.

Mỗi dòng đầu vào sẽ chứa 0 hoặc nhiều chữ số 0-9 theo sau bởi một hoặc nhiều chữ cái viết thường a-z. Bạn có thể lấy đầu vào và đưa ra đầu ra dưới dạng danh sách các chuỗi hoặc dưới dạng một chuỗi với các từ được phân tách bằng bất kỳ ký tự nào ngoài 0-9/ a-z.

Dưới đây là một trường hợp thử nghiệm nhỏ khác với một vài trường hợp cạnh không được nêu trong ví dụ:

abc cba 1de fg hi 0jkl mno abcdefghijk 10l
=> abc cba cde cfg chi jkl mno abcdefghijk abcdefghijl

Bạn cũng có thể kiểm tra mã của mình trên từ điển đầy đủ: đầu vào , đầu ra .


Có khả năng sẽ không có một số trong dòng thứ hai? Ngoài ra, chúng ta có thể cho rằng không có số nào ngoại trừ 0sẽ có 0s hàng đầu không?
Erik the Outgolfer 19/12/18

@EriktheOutgolfer Vâng, điều đó là có thể; Tôi đã thêm nó vào trường hợp thử nghiệm. Và vâng, bạn có thể giả sử rằng (cũng như số đó sẽ không lớn hơn độ dài của từ trước đó).
Doorknob

11
Đó là một định dạng nén dễ thương:]
Chọc

1
Các locatechương trình sử dụng loại mã hóa trên pathnames.
Dân D.

Tôi đã viết chương trình này để sử dụng thực tế của tôi, khoảng 15 năm trước. Thật không may, tôi không nghĩ rằng mình có nguồn nữa ...
hobbs 20/12/18

Câu trả lời:


13

Vim, 57 byte

:%s/\a/ &
:%norm +hkyiwjP
:g/\d/norm diw-@"yl+P
:%s/ //g

Hãy thử trực tuyến!


Sẽ <H<Gthay cho việc thay thế cuối cùng?
Kritixi Lithos

@cowsquack Thật không may, không. Mỗi đầu vào không bắt đầu bằng một số sẽ làm tăng số lượng khoảng trắng hàng đầu, vì vậy không có cách nào để đảm bảo một <giải pháp sẽ không đủ thời gian.
DJMcMayhem

Tôi nghĩ bạn có thể làm :%s/ *thay vì thay thế cuối cùng để lưu hai byte.
Dexter CD

10

JavaScript (ES6),  66 62  61 byte

a=>a.map(p=s=>a=a.slice([,x,y]=/(\d*)(.*)/.exec(s),p=x||p)+y)

Hãy thử trực tuyến!

Đã bình luận

a =>                  // a[] = input, re-used to store the previous word
  a.map(p =           // initialize p to a non-numeric value
  s =>                // for each string s in a[]:
    a =               //   update a:
      a.slice(        //     extract the correct prefix from the previous word:
        [, x, y] =    //       load into x and y:
          /(\d*)(.*)/ //         the result of a regular expression which splits the new
          .exec(s),   //         entry into x = leading digits and y = trailing letters
                      //       this array is interpreted as 0 by slice()
        p = x || p    //       update p to x if x is not an empty string; otherwise leave
                      //       it unchanged; use this as the 2nd parameter of slice()
      )               //     end of slice()
      + y             //     append the new suffix
  )                   // end of map()

5

Perl 6 , 50 48 byte

-2 byte nhờ nwellnhof

{my$l;.map:{$!=S[\d*]=substr $!,0,$l [R||]=~$/}}

Hãy thử trực tuyến!

Một cảng của giải pháp Arnauld . Man, R||mánh khóe đó là một tàu lượn siêu tốc từ 'Tôi nghĩ điều này có thể xảy ra', đến 'nah, điều đó là không thể', đến 'có thể là có thể' và cuối cùng là 'aha!'

Giải trình:

{my$l;.map:{$!=S[\d*]=substr $!,0,$l [R||]=~$/}}
{                                              }  # Anonymous code block
 my$l;    # Declare the variable $l, which is used for the previous number
      .map:{                                  }  # Map the input list to
            $!=              # $! is used to save the previous word
               S[\d*]=       # Substitute the number for
                      substr $!,0    # A substring of the previous word
                                 ,              # With the length of 
                                           ~$0     # The num if it exists
                                  $l [R||]=        # Otherwise the previous num

Phần $l [R||]=~$/gần như dịch sang $l= ~$/||+$lnhưng ... nó có cùng số lượng byte :(. Ban đầu, nó đã lưu các byte bằng một biến ẩn danh nên my$lđã biến mất nhưng điều đó không hoạt động vì phạm vi bây giờ là sự thay thế, không phải là mapcodeblock. Ồ tốt Dù sao, Rlà metaoperator đảo ngược, vì vậy nó đảo ngược các đối số của ||, vì vậy $lbiến cuối cùng được gán số mới ( ~$/) nếu nó tồn tại, nếu không thì lại tự lặp lại.

Nó có thể là 47 byte nếu Perl 6 không gây ra lỗi trình biên dịch dự phòng =~.


5

Ruby , 49 45 43 byte

$0=$_=$0[/.{0#{p=$_[/\d+/]||p}}/]+$_[/\D+/]

Hãy thử trực tuyến!

Giải trình

$0=                                         #Previous word, assign the value of
   $_=                                      #Current word, assign the value of
      $0[/.{0#{              }}/]           #Starting substring of $0 of length p which is
               p=$_[/\d+/]||p               #defined as a number in the start of $_ if any 
                                 +$_[/\D+/] #Plus any remaining non-digits in $_

5

C, 65 57 byte

n;f(){char c[99];while(scanf("%d",&n),gets(c+n))puts(c);}

Hãy thử trực tuyến!

Giải trình:

n;                     /* n is implicitly int, and initialized to zero. */

f() {                  /* the unpacking function. */

    char c[99];        /* we need a buffer to read into, for the longest line in
                          the full dictionary we need 12 + 1 bytes. */

    while(             /* loop while there is input left. */

        scanf("%d",&n) /* Read into n, if the read fails because this line
                          doesn't have a number n's value does not change.
                          scanf's return value is ignored. */

        ,              /* chain expressions with the comma operator. The loop
                          condition is on the right side of the comma. */

        gets(c+n))     /* we read into c starting from cₙ. c₀, c₁.. up to cₙ is
                          the shared prefix of the word we are reading and the
                          previous word. When gets is successful it returns c+n
                          else it will return NULL. When the loop condition is
                          NULL the loop exits. */

        puts(c);}      /* print the unpacked word. */

5

Brainfuck , 201 byte

,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,.[->+>+<<]>>----------]<[<<]>-<<<,]

Hãy thử trực tuyến!

Yêu cầu một dòng mới ở cuối đầu vào. Một phiên bản không có yêu cầu này dài hơn 6 byte:

Brainfuck , 207 byte

,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,[->+>+<<]>>[----------<.<]>>]<[<<]>-<<<,]

Hãy thử trực tuyến!

Cả hai phiên bản đều cho rằng tất cả các số đều nhỏ hơn 255.

Giải trình

Các băng được đặt ra như sau:

tempinputcopy 85 0 inputcopy number 1 a 1 a 1 r 1 d 0 w 0 o 0 l 0 f 0 ...

Ô "số" bằng 0 nếu không có chữ số nào được nhập và n + 1 nếu số n là đầu vào. Đầu vào được lấy tại ô được đánh dấu "85".

,[                     take input and start main loop
 [                     start number input loop
  [-<+>>>+<<]          copy input to tempinputcopy and inputcopy
  >-[---<+>]           put the number 85 in the cell where input was taken
  <[[-<]>>]            test whether input is less than 85; ending position depends on result of comparison
                       (note that digits are 48 through 57 while letters are 97 through 122)
  <[-]>                clean up by zeroing out the cell that didn't already become zero
  >[                   if input was a digit:
   <<,>>               get next input character
   >[-[-<++++++++++>]] multiply current value by 10 and add to current input
   ++++                set number cell to 4 (as part of subtracting 47)
   <[->+<]             add input plus 10*number back to number cell
   -[----->-<]         subtract 51
  <]                   move to cell we would be at if input were a letter
 <]                    move to input cell; this is occupied iff input was a digit

                       part 2: update/output word

 >>>                   move to number cell
 [                     if occupied (number was input):
  [>>]+[-<<]>>         remove existing marker 1s and decrement number cell to true value
  [[>>]+[<<]>>-]       create the correct amount of marker 1s
 ]
 +[>>]<[-]             zero out cell containing next letter from previous word
 <[<<]>                return to inputcopy
 [->[>>]<+<[<<]>]      move input copy to next letter cell
 >[>.>]                output word so far
 +[                    do until newline is read:
  >[-]<                zero out letter cell
  ,.                   input and output next letter or newline
  [->+>+<<]            copy to letter cell and following cell
  >>----------         subtract 10 to compare to newline
 ]
 <[<<]>-               zero out number cell (which was 1 to make copy loop shorter)
 <<<,                  return to input cell and take input
]                      repeat until end of input

4

Python 3.6 trở lên, 172 195 156 123 122 121 104 byte

import re
def f(l,n=0,w=""):
 for s in l:t=re.match("\d*",s)[0];n=int(t or n);w=w[:n]+s[len(t):];yield w

Hãy thử trực tuyến!

Giải trình

Tôi đã trích dẫn và sử dụng Biểu thức chính quy. Điều này đã lưu ít nhất 17 byte. :

t=re.match("\d*",s)[0]

Khi chuỗi không bắt đầu bằng một chữ số, độ dài của chuỗi này sẽ là 0. Điều này có nghĩa rằng:

n=int(t or n)

sẽ là nnếu ttrống rỗng, và int(t)nếu không.

w=w[:n]+s[len(t):]

xóa số mà biểu thức chính quy tìm thấy s(nếu không tìm thấy số nào, nó sẽ xóa các 0ký tự, không để lại ký tự s) và thay thế tất cả trừ các nký tự đầu tiên của từ trước đó bằng đoạn từ hiện tại; và:

yield w

xuất ra từ hiện tại.


4

Haskell, 82 81 byte

tail.map concat.scanl p["",""]
p[n,l]a|[(i,r)]<-reads a=[take i$n++l,r]|1<2=[n,a]

Lấy và trả về một danh sách các chuỗi.

Hãy thử trực tuyến!

        scanl p["",""]        -- fold function 'p' into the input list starting with
                              -- a list of two empty strings and collect the
                              -- intermediate results in a list
  p [n,l] a                   -- 1st string of the list 'n' is the part taken form the last word
                              -- 2nd string of the list 'l' is the part from the current line
                              -- 'a' is the code from the next line
     |[(i,r)]<-reads a        -- if 'a' can be parsed as an integer 'i' and a string 'r'
       =[take i$n++l,r]       -- go on with the first 'i' chars from the last line (-> 'n' and 'l' concatenated) and the new ending 'r'
     |1<2                     -- if parsing is not possible
       =[n,a]                 -- go on with the previous beginning of the word 'n' and the new end 'a'
                              -- e.g. [         "aa",     "2h",      "3ed",       "ing"       ] 
                              -- ->   [["",""],["","aa"],["aa","h"],["aah","ed"],["aah","ing"]]
  map concat                  -- concatenate each sublist
tail                          -- drop first element. 'scanl' saves the initial value in the list of intermediate results. 

Chỉnh sửa: -1 byte nhờ @Nitrodon.


1
Trái với trí tuệ chơi gôn Haskell thông thường, bạn thực sự có thể lưu một byte ở đây bằng cách không xác định hàm trợ giúp là toán tử infix.
Nitrodon

@Nitrodon: phát hiện tốt! Cảm ơn!
nimi

3

Japt, 19 18 17 byte

Ban đầu lấy cảm hứng từ giải pháp JS của Arnauld .

;£=¯V=XkB ªV +XoB

Thử nó

                      :Implicit input of string array U
 £                    :Map each X
   ¯                  :  Slice U to index
      Xk              :    Remove from X
;       B             :     The lowercase alphabet (leaving only the digits or an empty string, which is falsey)
          ªV          :    Logical OR with V (initially 0)
    V=                :    Assign the result to V for the next iteration
             +        :  Append
              Xo      :  Remove everything from X, except
;               B     :   The lowercase alphabet
  =                   :  Reassign the resulting string to U for the next iteration

2

Thạch , 16 byte

⁹fØDVo©®⁸ḣ;ḟØDµ\

Hãy thử trực tuyến!

Làm thế nào nó hoạt động

⁹fØDVo©®⁸ḣ;ḟØDµ\  Main link. Argument: A (array of strings)

              µ\  Cumulatively reduce A by the link to the left.
⁹                     Yield the right argument.
  ØD                  Yield "0123456789".
 f                    Filter; keep only digits.
    V                 Eval the result. An empty string yields 0.
     o©               Perform logical OR and copy the result to the register.
       ®              Yield the value in the register (initially 0).
        ⁸ḣ            Head; keep that many character of the left argument.
          ;           Concatenate the result and the right argument.
            ØD        Yield "0123456789".
           ḟ          Filterfalse; keep only non-digits.


1

Võng mạc 0.8.2 , 69 byte

+`((\d+).*¶)(\D)
$1$2$3
\d+
$*
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3

Hãy thử trực tuyến! Liên kết bao gồm các trường hợp thử nghiệm khó hơn. Giải trình:

+`((\d+).*¶)(\D)
$1$2$3

Đối với tất cả các dòng bắt đầu bằng chữ cái, sao chép số từ dòng trước đó, lặp cho đến khi tất cả các dòng bắt đầu bằng một số.

\d+
$*

Chuyển đổi số thành unary.

+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3

Sử dụng các nhóm cân bằng để thay thế tất cả 1s bằng chữ cái tương ứng từ dòng trước. (Điều này hóa ra hơi nặng hơn so với việc thay thế tất cả các lần chạy của 1s.)




1

Groovy , 74 byte

{w="";d=0;it.replaceAll(/(\d*)(.+)/){d=(it[1]?:d)as int;w=w[0..<d]+it[2]}}

Hãy thử trực tuyến!

Giải trình:

{                                                                        }  Closure, sole argument = it
 w="";d=0;                                                                  Initialize variables
          it.replaceAll(/(\d*)(.+)/){                                   }   Replace every line (since this matches every line) and implicitly return. Loop variable is again it
                                     d=(it[1]?:d)as int;                    If a number is matched, set d to the number as an integer, else keep the value
                                                        w=w[0..<d]+it[2]    Set w to the first d characters of w, plus the matched string


0

Perl 5 -p , 45 41 byte

s:\d*:substr($p,0,$l=$&+$l*/^\D/):e;$p=$_

Hãy thử trực tuyến!

Giải trình:

s:\d*:substr($p,0,$l=$&+$l*/^\D/):e;$p=$_ Full program, implicit input
s:   :                           :e;      Replace
  \d*                                       Any number of digits
      substr($p,0,              )           By a prefix of $p (previous result or "")
                  $l=  +                      With a length (assigned to $l) of the sum
                     $&                         of the matched digits
                          *                     and the product
                        $l                        of $l (previous length or 0)
                           /^\D/                  and whether there is no number in the beginning (1 or 0)
                                                (product is $l if no number)
                                    $p=$_ Assign output to $p
                                          Implicit output


0

05AB1E , 20 19 17 byte

õUvyþDõÊi£U}Xyá«=

Hãy thử trực tuyến hoặc xác minh tất cả các trường hợp thử nghiệm .

Giải trình:

õ                  # Push an empty string ""
 U                 # Pop and store it in variable `X`
v                  # Loop `y` over the (implicit) input-list
 yþ                #  Push `y`, and leave only the digits (let's call it `n`)
   DõÊi  }         #  If it's NOT equal to an empty string "":
       £           #   Pop and push the first `n` characters of the string
        U          #   Pop and store it in variable `X`
          X        #  Push variable `X`
           yá      #  Push `y`, and leave only the letters
             «     #  Merge them together
              =    #  Print it (without popping)

0

Lisp thông thường, 181 byte

(do(w(p 0))((not(setf g(read-line t()))))(multiple-value-bind(a b)(parse-integer g :junk-allowed t)(setf p(or a p)w(concatenate'string(subseq w 0 p)(subseq g b)))(format t"~a~%"w)))

Hãy thử trực tuyến!

Ung dung:

(do (w (p 0))   ; w previous word, p previous integer prefix (initialized to 0)
    ((not (setf g (read-line t ()))))   ; read a line into new variable g
                                        ; and if null terminate: 
  (multiple-value-bind (a b)            ; let a, b the current integer prefix
      (parse-integer g :junk-allowed t) ; and the position after the prefix
    (setf p (or a p)                    ; set p to a (if nil (no numeric prefix) to 0)
          w (concatenate 'string        ; set w to the concatenation of prefix
             (subseq w 0 p)             ; characters from the previous word 
             (subseq g b)))             ; and the rest of the current line
    (format t"~a~%"w)))                 ; print the current word

Như thường lệ, các định danh dài của Common Lisp khiến nó không đặc biệt phù hợp với PPCG.



0

C # (Trình biên dịch tương tác Visual C #) , 134 byte

a=>{int l=0,m,n;var p="";return a.Select(s=>{for(m=n=0;s[m]<58;n=n*10+s[m++]-48);return p=p.Substring(0,l=m>0?n:l)+s.Substring(m);});}

Hãy thử trực tuyến!

-9 byte nhờ @ASCIIOnly!

Ít chơi gôn hơn ...

// a is an input list of strings
a=>{
  // l: last prefix length
  // m: current number of digits
  // n: current prefix length
  int l=0,m,n;
  // previous word
  var p="";
  // run a LINQ select against the input
  // s is the current word
  return a.Select(s=>{
    // nibble digits from start of the
    // current word to build up the
    // current prefix length
    for(m=n=0;
      s[m]<58;
      n=n*10+s[m++]-48);
    // append the prefix from the
    // previous word to the current
    // word and capture values
    // for the next iteration
    return
      p=p.Substring(0,l=m>0?n:l)+
      s.Substring(m);
  });
}


Điều đó thật tuyệt :) Tôi đã đổi l=n>0?n:lthành l=m>0?n:lvì nó không chọn trường hợp khi một dòng bắt đầu bằng zero ( 0jkl). Cảm ơn vì tiền hỗ trợ!
dana

0

Scala , 226 129 102 byte

Cảm ơn @ ASCII - chỉ cho công việc của họ ở đây (và cho câu trả lời Groovy).

s=>{var(w,d,r)=("",0,"(\\d*)(.+)".r)
s map(_ match{case r(a,b)=>{if(a>"")d=a.toInt
w=w.take(d)+b}
w})}

Hãy thử trực tuyến!


: | cả hai liên kết đều giống nhau
ASCII

vâng, chỉnh sửa. Tôi không biết làm thế nào để tắt nó đi và vội vàng vì vậy tôi đã không sửa đổi những gì tôi đã làm.
V. Courtois



Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.