แยกวิเคราะห์รูปแบบพจนานุกรม Bookworm


42

เมื่อไม่นานมานี้ฉันได้ดื่มด่ำกับความคิดถึงในรูปแบบของ Bookworm Deluxe:

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

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

กฎสำหรับการคลายพจนานุกรมง่ายมาก:

  1. อ่านตัวเลขที่จุดเริ่มต้นของบรรทัดและคัดลอกอักขระจำนวนมากจากจุดเริ่มต้นของคำก่อนหน้า (หากไม่มีตัวเลขให้คัดลอกตัวอักษรให้มากที่สุดครั้งที่แล้ว)

  2. ผนวกตัวอักษรต่อไปนี้เข้ากับคำ

ดังนั้นคำแรกของเราจะaaตามมาด้วย2hซึ่งหมายถึง "คัดลอกตัวอักษรสองตัวแรกของaaและผนวกh" aahการขึ้นรูป จากนั้นก็3edจะกลายเป็นaahedและตั้งแต่บรรทัดถัดไปไม่ได้มีจำนวนที่เราคัดลอก 3 aahingตัวอักษรอีกครั้งเพื่อรูปแบบ กระบวนการนี้จะดำเนินต่อไปตลอดพจนานุกรมที่เหลือ คำที่เป็นผลลัพธ์จากอินพุตตัวอย่างขนาดเล็กคือ:

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

ความท้าทายของคุณคือการเปิดออกในไม่กี่ไบต์เท่าที่จะทำได้

สายของท่านแต่ละคนจะมีศูนย์หรือมากกว่าตัวเลขตามด้วยหนึ่งหรือมากกว่าตัวอักษรตัวพิมพ์เล็ก0-9 a-zคุณอาจใช้เวลาเข้าและส่งออกให้เป็นทั้งรายการของสตริงหรือเป็นสายเดียวด้วยคำพูดที่แยกจากกันโดยตัวละครอื่น ๆ กว่าใด ๆ/0-9a-z

นี่คืออีกกรณีทดสอบขนาดเล็กที่มีกรณีขอบไม่กี่ไม่ครอบคลุมในตัวอย่าง:

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

นอกจากนี้คุณยังอาจทดสอบรหัสของคุณในพจนานุกรมเต็ม: อินพุต , เอาท์พุท


มีความเป็นไปได้ไหมที่จะไม่มีตัวเลขในบรรทัดที่สอง? นอกจากนี้เราสามารถสมมติว่าไม่มีตัวเลขยกเว้น0จะมีผู้นำ0หรือไม่
Erik the Outgolfer

@EriktheOutgolfer ใช่นั่นเป็นไปได้ ฉันได้เพิ่มไปยังกรณีทดสอบ และใช่คุณสามารถสันนิษฐานได้ว่า (รวมถึงจำนวนนั้นจะไม่มากกว่าความยาวของคำก่อนหน้า)
ลูกบิดประตู

11
นั่นเป็นรูปแบบการบีบอัดที่น่ารัก:]
Poke

1
locateโปรแกรมใช้ประเภทของการเข้ารหัสบน pathnames นี้
Dan D.

ฉันเขียนโปรแกรมนี้สำหรับการใช้งานจริงของฉันประมาณ 15 ปีที่แล้ว แต่น่าเสียดายที่ฉันไม่คิดว่าฉันมีแหล่งที่มาอีกต่อไป ...
ฮอบส์

คำตอบ:


13

เป็นกลุ่ม, 57 ไบต์

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

ลองออนไลน์!


จะ<H<Gแทนการทำงานเปลี่ยนตัวสุดท้าย?
Kritixi Lithos

@cowsquack น่าเสียดายที่ไม่มี ทุกอินพุตที่ไม่ได้ขึ้นต้นด้วยตัวเลขจะเพิ่มจำนวนของช่องว่างนำหน้าดังนั้นจึงไม่มีวิธีใดที่จะรับประกันได้ว่า<โซลูชันจะรวมเวลาเข้าด้วยกันไม่เพียงพอ
DJMcMayhem

ฉันคิดว่าคุณสามารถทำได้:%s/ *แทนการทดแทนครั้งล่าสุดเพื่อบันทึกสองไบต์
เด็กซ์เตอร์ซีดี

10

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

Perl 6 , 50 48 ไบต์

-2 ไบต์ต้องขอบคุณ nwellnhof

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

ลองออนไลน์!

พอร์ตของการแก้ปัญหาของ Arnauld ชายR||กลอุบายนั้นเป็นรถไฟเหาะตีลังกาจาก 'ฉันคิดว่ามันเป็นไปได้' ถึง 'ไม่มันเป็นไปไม่ได้' ถึง 'อาจจะเป็นไปได้' และในที่สุดก็ 'aha!'

คำอธิบาย:

{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มันหายไป แต่มันไม่ได้ผลเพราะตอนนี้ขอบเขตคือการแทนที่ไม่ใช่mapcodeblock โอ้ดี อย่างไรก็ตามRมันคือ metaoperator แบบย้อนกลับดังนั้นจึงกลับอาร์กิวเมนต์ของ||ดังนั้น$lตัวแปรจะสิ้นสุดลงเมื่อมีการกำหนดหมายเลขใหม่ ( ~$/) ถ้ามีอยู่มิฉะนั้นจะเกิดขึ้นเอง

มันอาจจะเป็น 47 ไบต์ถ้า Perl 6 =~ไม่ได้โยนความผิดพลาดซ้ำซ้อนคอมไพเลอร์ครับสำหรับ



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

เซลล์ "number" เท่ากับ 0 ถ้าไม่มีตัวเลขเป็นอินพุตและ n + 1 หากตัวเลข n เป็นอินพุต อินพุตถูกนำไปที่เซลล์ที่ระบุว่า "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+ 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ถ้าtว่างเปล่าและไม่int(t)เช่นนั้น

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

ลบตัวเลขที่พบจากการแสดงออกปกติs(หากไม่พบตัวเลขมันจะลบ0ตัวอักษรออกโดยไม่ถูกsยกเลิก) และแทนที่ทั้งหมดยกเว้นnอักขระตัวแรกของคำก่อนหน้านี้ด้วยการแยกส่วนคำปัจจุบัน และ:

yield w

ส่งออกคำปัจจุบัน


4

Haskell, 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. 

แก้ไข: -1 ไบต์ขอบคุณ @Nitrodon


1
ตรงกันข้ามกับภูมิปัญญาการเล่นกอล์ฟของ Haskell ปกติคุณสามารถบันทึกหนึ่งไบต์ที่นี่ได้โดยไม่ต้องกำหนดฟังก์ชันตัวช่วยเป็นตัวดำเนินการมัด
Nitrodon

@Nitrodon: ด่างดี! ขอบคุณ!
nimi

3

Japt, 19 18 17 ไบต์

แรงบันดาลใจในขั้นต้นโดยวิธีการแก้ปัญหาของ JS Arnauld

;£=¯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

ใช้กลุ่มที่สมดุลเพื่อแทนที่1s ทั้งหมดด้วยตัวอักษรที่สอดคล้องกันจากบรรทัดก่อนหน้า (สิ่งนี้กลายเป็นนักกอล์ฟเล็กน้อยกว่าการแทนที่การวิ่งทั้งหมด1)




1

Groovy , 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

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

ลองออนไลน์!

Ungolfed:

(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 # Interactive Compiler) , 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);});}

ลองออนไลน์!

-9 ไบต์ขอบคุณ @ASCIIOnly!

น้อย golfed ...

// 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:lเป็นl=m>0?n:lเพราะมันไม่ได้ยกเคสเมื่อบรรทัดเริ่มต้นด้วยศูนย์ ( 0jkl) ขอบคุณสำหรับทิป!
dana

0

สกาลา , 226 129 102 ไบต์

ขอบคุณ @ ASCII- เฉพาะสำหรับงานของพวกเขาที่นี่ (และสำหรับคำตอบ 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})}

ลองออนไลน์!


: | ลิงก์ทั้งสองเหมือนกัน
เฉพาะ ASCII เท่านั้น

ใช่การแก้ไข ฉันไม่ทราบวิธีเปิดใช้งานและรีบเร่งดังนั้นฉันจึงไม่ได้แก้ไขสิ่งที่ฉันทำ
V. Courtois



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