책벌레 사전 형식 분석


42

나는 최근에 Bookworm Deluxe의 형태로 향수에 빠져 있습니다.

이전에 보지 못한 경우 인접한 타일을 연결하여 단어를 만드는 것이 목표 인 단어 게임입니다. 문자열이 유효한 단어인지 확인하기 위해 다음과 같은 압축 형식으로 저장된 내부 사전과 비교하여 확인합니다.

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

사전 포장 풀기 규칙은 간단합니다.

  1. 줄의 시작 부분에있는 숫자를 읽고 이전 단어의 시작 부분부터 많은 문자를 복사하십시오. (숫자가 없으면 지난번처럼 문자를 복사하십시오.)

  2. 다음 글자를 단어에 추가하십시오.

그래서, 우리의 첫 번째 단어가되어 aa, 다음에 2h"의 첫 두 글자를 복사 수단이되는, aaAPPEND 및 h형성" aah. 그런 3ed다음가되고 aahed다음 줄에는 숫자가 없으므로 3자를 다시 복사하여를 aahing만듭니다. 이 과정은 나머지 사전에 걸쳐 계속됩니다. 작은 샘플 입력의 결과 단어는 다음과 같습니다.

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

가능한 한 적은 바이트로 압축 풀기를 수행해야합니다.

각 입력 행에는 0 개 이상의 숫자 0-9 와 하나 이상의 소문자 가 포함됩니다 a-z. 입력을 받아서 출력을 문자열 목록 또는 0-9/ 이외의 다른 문자로 구분 된 단어가있는 단일 문자열로 제공 할 수 있습니다 a-z.

다음은 예제에서 다루지 않은 몇 가지 엣지 케이스가있는 또 다른 작은 테스트 케이스입니다.

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

전체 사전 ( input , output) 에서 코드를 테스트 할 수도 있습니다 .


두 번째 줄에 숫자가 없을 가능성이 있습니까? 또한 00의 숫자를 제외한 숫자가 없다고 가정 할 수 있습니까?
Outgolfer Erik

@EriktheOutgolfer 예, 가능합니다. 테스트 케이스에 추가했습니다. 그리고 예, 당신은 (그리고 숫자가 이전 단어의 길이보다 크지 않을 것이라고) 가정 할 수 있습니다.
Doorknob

11
그것은 귀여운 압축 형식입니다.]
Poke

1
locate프로그램에 패스 인코딩의 유형을 사용한다.
Dan D.

나는 약 15 년 전에 실제 사용을 위해이 프로그램을 작성했습니다. 불행히도 나는 더 이상 소스를 가지고 있다고 생각하지 않습니다 ...
hobbs

답변:


13

Vim, 57 바이트

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

온라인으로 사용해보십시오!


겠습니까 <H<G대신 마지막 교체 작업?
Kritixi Lithos

@cowsquack 불행하게도, 아니. 숫자로 시작하지 않는 모든 입력은 선행 공백의 수를 증가 시키므로< 솔루션이 충분한 시간을 들여 쓰지 않도록 보장 할 방법이 없습니다 .
DJMcMayhem

:%s/ *마지막 대체 대신 두 바이트를 절약 할 수 있다고 생각합니다 .
덱스터 CD

10

자바 스크립트 (ES6),  66 62  61 바이트

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

온라인으로 사용해보십시오!

댓글

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

펄 6 , 50 48 바이트

nwellnhof 덕분에 -2 바이트

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

온라인으로 사용해보십시오!

Arnauld 솔루션 의 포트 . 남자, 그 R||속임수는 '이것은 가능할 것 같아요', '아냐, 불가능하다', '킨다 어쩌면 가능하다'그리고 마지막으로 '아하!'의 롤러 코스터였습니다.

설명:

{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

$l [R||]=~$/부분은 대략적으로 번역 $l= ~$/||+$l되지만 ... 같은 양의 바이트를 갖습니다 :(. 원래 익명 변수를 사용하여 바이트를 저장했기 때문에 my$l가 사라졌지 만 범위는 이제 코드 map블록이 아니라 대체이므로 작동하지 않습니다 . 오 잘 여하튼, R이 인자의 반전되도록 역방향 metaoperator이며, ||소위, $l업 변수 단부 새로운 번호 (할당되어 ~$/)이 존재하는 경우, 그렇지 않으면 다시 자체.

Perl 6이에 대한 일종의 중복 컴파일러 오류를 발생시키지 않으면 47 바이트 일 수 있습니다 =~.


5

루비 , 49 45 43 바이트

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

온라인으로 사용해보십시오!

설명

$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 바이트

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

온라인으로 사용해보십시오!

설명:

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 바이트

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

온라인으로 사용해보십시오!

입력 끝에 줄 바꿈이 필요합니다. 이 요구 사항이없는 버전은 6 바이트 더 깁니다.

brainfuck , 207 바이트

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

온라인으로 사용해보십시오!

두 버전 모두 모든 숫자가 255보다 작다고 가정합니다.

설명

테이프는 다음과 같이 배치됩니다.

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

숫자가 입력되지 않으면 "숫자"셀은 0이되고, 숫자 n이 입력되면 n + 1이됩니다. "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

파이썬 3.6 이상 172 195 156 123 122 121 104 바이트

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

온라인으로 사용해보십시오!

설명

나는 정규 표현식을 사용했습니다. 이것은 최소 17 바이트를 절약했습니다. :

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

문자열이 숫자로 시작하지 않으면이 문자열의 길이는입니다 0. 이것은 다음을 의미합니다.

n=int(t or n)

될 것입니다 n경우 tIS가 비워하고, int(t)그렇지 않으면.

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

정규식에서 찾은 숫자를 제거하고 (숫자가 s없으면 0문자를 제거 s하고 잘리지 않은 채로 남겨 둠 ) n이전 단어 의 첫 문자를 제외한 모든 문자를 현재 단어 조각으로 바꿉니다 . 과:

yield w

현재 단어를 출력합니다.


4

하스켈, 82 81 바이트

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

문자열 목록을 가져 와서 반환합니다.

온라인으로 사용해보십시오!

        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. 

편집 : @Nitrodon 덕분에 -1 바이트.


1
일반적인 Haskell 골프의 지혜와는 달리 도우미 함수를 삽입 연산자로 정의 하지 않으면 실제로 1 바이트를 절약 할 수 있습니다 .
Nitrodon

@Nitrodon : 잘 발견되었습니다! 감사!
nimi

3

apt, 19 18 17 바이트

Arnauld의 JS 솔루션에서 처음 영감을 받았습니다 .

;£=¯V=XkB ªV +XoB

시도 해봐

                      :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

젤리 , 16 바이트

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

온라인으로 사용해보십시오!

작동 원리

⁹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

레티 나 0.8.2 , 69 바이트

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

온라인으로 사용해보십시오! 더 어려운 테스트 사례가 포함되어 있습니다. 설명:

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

문자로 시작하는 모든 행의 경우 모든 행이 숫자로 시작될 때까지 반복하여 이전 행의 숫자를 복사하십시오.

\d+
$*

숫자를 단항으로 변환하십시오.

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

균형 그룹을 사용하여 모든 1행을 이전 행의 해당 문자로 바꿉니다. (이것은 모든 런을 교체하는 것보다 약간 골퍼로 판명되었습니다 1.)




1

그루비 , 74 바이트

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

온라인으로 사용해보십시오!

설명:

{                                                                        }  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

펄 5 -p , 45 41 바이트

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

온라인으로 사용해보십시오!

설명:

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 바이트

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

온라인으로 시도 하거나 모든 테스트 사례를 확인하십시오 .

설명:

õ                  # 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

공통 리스프, 181 바이트

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

온라인으로 사용해보십시오!

언 골프 드 :

(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

평소와 같이 Common Lisp의 긴 식별자는 PPCG에 적합하지 않습니다.



0

C # (Visual C # 대화식 컴파일러) , 134 바이트

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

온라인으로 사용해보십시오!

@ASCIIOnly 덕분에 -9 바이트!

덜 골프 ...

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


그건 꽤 멋진 :) 내가 변경 l=n>0?n:ll=m>0?n:l라인이 0으로 시작 때 (사건을 따기되지 않았기 때문에 0jkl). 팁 고마워!
dana

0

스칼라 , 226 (129) 102 바이트

그들의 작업 (그리고 Groovy 답변)에 대한 @ASCII 전용 감사합니다.

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

온라인으로 사용해보십시오!


: | 두 링크 모두 동일합니다
ASCII 전용

예, 편집 나는 그것을 끄는 방법을 몰랐고 서둘러서 내가 한 일을 수정하지 않았습니다.
V. Courtois



당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.