Parse the Bookworm dictionary format
I've recently been indulging myself in some nostalgia
in the form of Bookworm Deluxe:

In case you haven't seen it before,
it's a word game where the goal is to connect adjacent tiles to form words.
In order to determine whether a string is a valid word,
it checks it against its internal dictionary,
which is stored in a compressed format that looks like this:
aa
2h
3ed
ing
s
2l
3iis
s
2rdvark
8s
4wolf
7ves
The rules for unpacking the dictionary are simple:
Read the number at the start of the line,
and copy that many characters from the beginning of the previous word.
(If there is no number,
copy as many characters as you did last time.)Append the following letters to the word.
So, our first word is aa,
followed by 2h,
which means "copy the first two letters of aa and append h,"
forming aah.
Then 3ed becomes aahed,
and since the next line doesn't have a number,
we copy 3 characters again to form aahing.
This process continues throughout the rest of the dictionary.
The resulting words from the small sample input are:
aa
aah
aahed
aahing
aahs
aal
aaliis
aals
aardvark
aardvarks
aardwolf
aardwolves
Your challenge is to perform this unpacking
in as few bytes as possible.
Each line of input will contain zero or more digits 0-9
followed by one or more lowercase letters a-z.
You may take input and give output
as either a list of strings,
or as a single string with words separated by any character other than 0-9/a-z.
Here is another small test case
with a few edge cases not covered in the example:
abc cba 1de fg hi 0jkl mno abcdefghijk 10l
=> abc cba cde cfg chi jkl mno abcdefghijk abcdefghijl
You may also test your code on the full dictionary:
input,
output.
code-golf string
|
show 1 more comment
I've recently been indulging myself in some nostalgia
in the form of Bookworm Deluxe:

In case you haven't seen it before,
it's a word game where the goal is to connect adjacent tiles to form words.
In order to determine whether a string is a valid word,
it checks it against its internal dictionary,
which is stored in a compressed format that looks like this:
aa
2h
3ed
ing
s
2l
3iis
s
2rdvark
8s
4wolf
7ves
The rules for unpacking the dictionary are simple:
Read the number at the start of the line,
and copy that many characters from the beginning of the previous word.
(If there is no number,
copy as many characters as you did last time.)Append the following letters to the word.
So, our first word is aa,
followed by 2h,
which means "copy the first two letters of aa and append h,"
forming aah.
Then 3ed becomes aahed,
and since the next line doesn't have a number,
we copy 3 characters again to form aahing.
This process continues throughout the rest of the dictionary.
The resulting words from the small sample input are:
aa
aah
aahed
aahing
aahs
aal
aaliis
aals
aardvark
aardvarks
aardwolf
aardwolves
Your challenge is to perform this unpacking
in as few bytes as possible.
Each line of input will contain zero or more digits 0-9
followed by one or more lowercase letters a-z.
You may take input and give output
as either a list of strings,
or as a single string with words separated by any character other than 0-9/a-z.
Here is another small test case
with a few edge cases not covered in the example:
abc cba 1de fg hi 0jkl mno abcdefghijk 10l
=> abc cba cde cfg chi jkl mno abcdefghijk abcdefghijl
You may also test your code on the full dictionary:
input,
output.
code-golf string
Is there a possibility that there will not be a number in the second line? Also, can we assume that no number except0will have leading0s?
– Erik the Outgolfer
Dec 19 at 19:43
@EriktheOutgolfer Yes, that is possible; I've added that to the test case. And yes, you can assume that (as well as that the number won't be greater than the length of the previous word).
– Doorknob♦
Dec 19 at 19:46
9
That's a cute compression format :]
– Poke
Dec 19 at 20:19
1
Thelocateprogram uses this type of encoding on pathnames.
– Dan D.
Dec 19 at 21:24
I wrote this program for my actual use, about 15 years ago. Unfortunately I don't think I have the source anymore...
– hobbs
Dec 20 at 1:24
|
show 1 more comment
I've recently been indulging myself in some nostalgia
in the form of Bookworm Deluxe:

In case you haven't seen it before,
it's a word game where the goal is to connect adjacent tiles to form words.
In order to determine whether a string is a valid word,
it checks it against its internal dictionary,
which is stored in a compressed format that looks like this:
aa
2h
3ed
ing
s
2l
3iis
s
2rdvark
8s
4wolf
7ves
The rules for unpacking the dictionary are simple:
Read the number at the start of the line,
and copy that many characters from the beginning of the previous word.
(If there is no number,
copy as many characters as you did last time.)Append the following letters to the word.
So, our first word is aa,
followed by 2h,
which means "copy the first two letters of aa and append h,"
forming aah.
Then 3ed becomes aahed,
and since the next line doesn't have a number,
we copy 3 characters again to form aahing.
This process continues throughout the rest of the dictionary.
The resulting words from the small sample input are:
aa
aah
aahed
aahing
aahs
aal
aaliis
aals
aardvark
aardvarks
aardwolf
aardwolves
Your challenge is to perform this unpacking
in as few bytes as possible.
Each line of input will contain zero or more digits 0-9
followed by one or more lowercase letters a-z.
You may take input and give output
as either a list of strings,
or as a single string with words separated by any character other than 0-9/a-z.
Here is another small test case
with a few edge cases not covered in the example:
abc cba 1de fg hi 0jkl mno abcdefghijk 10l
=> abc cba cde cfg chi jkl mno abcdefghijk abcdefghijl
You may also test your code on the full dictionary:
input,
output.
code-golf string
I've recently been indulging myself in some nostalgia
in the form of Bookworm Deluxe:

In case you haven't seen it before,
it's a word game where the goal is to connect adjacent tiles to form words.
In order to determine whether a string is a valid word,
it checks it against its internal dictionary,
which is stored in a compressed format that looks like this:
aa
2h
3ed
ing
s
2l
3iis
s
2rdvark
8s
4wolf
7ves
The rules for unpacking the dictionary are simple:
Read the number at the start of the line,
and copy that many characters from the beginning of the previous word.
(If there is no number,
copy as many characters as you did last time.)Append the following letters to the word.
So, our first word is aa,
followed by 2h,
which means "copy the first two letters of aa and append h,"
forming aah.
Then 3ed becomes aahed,
and since the next line doesn't have a number,
we copy 3 characters again to form aahing.
This process continues throughout the rest of the dictionary.
The resulting words from the small sample input are:
aa
aah
aahed
aahing
aahs
aal
aaliis
aals
aardvark
aardvarks
aardwolf
aardwolves
Your challenge is to perform this unpacking
in as few bytes as possible.
Each line of input will contain zero or more digits 0-9
followed by one or more lowercase letters a-z.
You may take input and give output
as either a list of strings,
or as a single string with words separated by any character other than 0-9/a-z.
Here is another small test case
with a few edge cases not covered in the example:
abc cba 1de fg hi 0jkl mno abcdefghijk 10l
=> abc cba cde cfg chi jkl mno abcdefghijk abcdefghijl
You may also test your code on the full dictionary:
input,
output.
code-golf string
code-golf string
edited Dec 19 at 19:45
asked Dec 19 at 19:37
Doorknob♦
54.2k17113345
54.2k17113345
Is there a possibility that there will not be a number in the second line? Also, can we assume that no number except0will have leading0s?
– Erik the Outgolfer
Dec 19 at 19:43
@EriktheOutgolfer Yes, that is possible; I've added that to the test case. And yes, you can assume that (as well as that the number won't be greater than the length of the previous word).
– Doorknob♦
Dec 19 at 19:46
9
That's a cute compression format :]
– Poke
Dec 19 at 20:19
1
Thelocateprogram uses this type of encoding on pathnames.
– Dan D.
Dec 19 at 21:24
I wrote this program for my actual use, about 15 years ago. Unfortunately I don't think I have the source anymore...
– hobbs
Dec 20 at 1:24
|
show 1 more comment
Is there a possibility that there will not be a number in the second line? Also, can we assume that no number except0will have leading0s?
– Erik the Outgolfer
Dec 19 at 19:43
@EriktheOutgolfer Yes, that is possible; I've added that to the test case. And yes, you can assume that (as well as that the number won't be greater than the length of the previous word).
– Doorknob♦
Dec 19 at 19:46
9
That's a cute compression format :]
– Poke
Dec 19 at 20:19
1
Thelocateprogram uses this type of encoding on pathnames.
– Dan D.
Dec 19 at 21:24
I wrote this program for my actual use, about 15 years ago. Unfortunately I don't think I have the source anymore...
– hobbs
Dec 20 at 1:24
Is there a possibility that there will not be a number in the second line? Also, can we assume that no number except
0 will have leading 0s?– Erik the Outgolfer
Dec 19 at 19:43
Is there a possibility that there will not be a number in the second line? Also, can we assume that no number except
0 will have leading 0s?– Erik the Outgolfer
Dec 19 at 19:43
@EriktheOutgolfer Yes, that is possible; I've added that to the test case. And yes, you can assume that (as well as that the number won't be greater than the length of the previous word).
– Doorknob♦
Dec 19 at 19:46
@EriktheOutgolfer Yes, that is possible; I've added that to the test case. And yes, you can assume that (as well as that the number won't be greater than the length of the previous word).
– Doorknob♦
Dec 19 at 19:46
9
9
That's a cute compression format :]
– Poke
Dec 19 at 20:19
That's a cute compression format :]
– Poke
Dec 19 at 20:19
1
1
The
locate program uses this type of encoding on pathnames.– Dan D.
Dec 19 at 21:24
The
locate program uses this type of encoding on pathnames.– Dan D.
Dec 19 at 21:24
I wrote this program for my actual use, about 15 years ago. Unfortunately I don't think I have the source anymore...
– hobbs
Dec 20 at 1:24
I wrote this program for my actual use, about 15 years ago. Unfortunately I don't think I have the source anymore...
– hobbs
Dec 20 at 1:24
|
show 1 more comment
19 Answers
19
active
oldest
votes
Vim, 57 bytes
:%s/a/ &
:%norm +hkyiwjP
:g/d/norm diw-@"yl+P
:%s/ //g
Try it online!
Would<H<Ginstead of the last substitution work?
– Cows quack
yesterday
@cowsquack Unfortunately, no. Every input that doesn't start with a number increases the number of leading spaces so there's no way to guarantee a<solution would unindent enough times.
– DJMcMayhem♦
yesterday
add a comment |
JavaScript (ES6), 66 62 61 bytes
a=>a.map(p=s=>a=a.slice([,x,y]=/(d*)(.*)/.exec(s),p=x||p)+y)
Try it online!
Commented
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()
add a comment |
Perl 6, 50 48 bytes
-2 bytes thanks to nwellnhof
{my$l;.map:{$!=S[d*]=substr $!,0,$l [R||]=~$/}}
Try it online!
A port of Arnauld's solution. Man, that R|| trick was a rollercoaster from 'I think this could be possible', to 'nah, it's impossible', to 'kinda maybe possible' and finally 'aha!'
Explanation:
{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
The $l [R||]=~$/ part roughly translates to $l= ~$/||+$l but... it has the same amount of bytes :(. Originally, it saved bytes using an anonymous variable so the my$l was gone but that doesn't work since the scope is now the substitution, not the map codeblock. Oh well. Anyways, R is the reverse metaoperator, so it reverses the arguments of ||, so the $l variable ends up being assigned the new number (~$/) if it exists, otherwise itself again.
It could be 47 bytes if Perl 6 didn't throw a kinda redundant compiler error for =~.
add a comment |
Ruby, 49 45 43 bytes
$0=$_=$0[/.{0#{p=$_[/d+/]||p}}/]+$_[/D+/]
Try it online!
Explanation
$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 $_
add a comment |
Haskell, 82 81 bytes
tail.map concat.scanl p["",""]
p[n,l]a|[(i,r)]<-reads a=[take i$n++l,r]|1<2=[n,a]
Takes and returns a list of strings.
Try it online!
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.
Edit: -1 byte thanks to @Nitrodon.
1
Contrary to usual Haskell golfing wisdom, you can actually save one byte here by not defining the helper function as an infix operator.
– Nitrodon
20 hours ago
@Nitrodon: well spotted! Thanks!
– nimi
14 hours ago
add a comment |
Japt, 19 18 17 bytes
Initially inspired by Arnauld's JS solution.
;£=¯V=XkB ªV +XoB
Try it
: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
add a comment |
Python 3.6+, 172 195 156 123 122 121 104 bytes
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
- -12 bytes thanks to Bubbler
- -5 bytes thanks to Dennis
Try it online!
Explanation
I caved, and used Regular Expressions. This saved at least 17 bytes. :
t=re.match("d*",s)[0]
When the string doesn't begin with a digit at all, the length of this string will be 0. This means that:
n=int(t or n)
will be n if t is empty, and int(t) otherwise.
w=w[:n]+s[len(t):]
removes the number that the regular expression found from s (if there's no number found, it'll remove 0 characters, leaving s untruncated) and replaces all but the first n characters of the previous word with the current word fragment; and:
yield w
outputs the current word.
add a comment |
Jelly, 16 bytes
⁹fØDVo©®⁸ḣ;ḟØDµ
Try it online!
How it works
⁹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.
add a comment |
C, 65 57 bytes
n;f(){char c[99];while(scanf("%d",&n),gets(c+n))puts(c);}
Try it online!
Explanation:
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. */
New contributor
Dexter CD is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
brainfuck, 201 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,.[->+>+<<]>>----------]<[<<]>-<<<,]
Try it online!
Requires a trailing newline at the end of the input. A version without this requirement is 6 bytes longer:
brainfuck, 207 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,[->+>+<<]>>[----------<.<]>>]<[<<]>-<<<,]
Try it online!
Both versions assume all numbers are strictly less than 255.
Explanation
The tape is laid out as follows:
tempinputcopy 85 0 inputcopy number 1 a 1 a 1 r 1 d 0 w 0 o 0 l 0 f 0 ...
The "number" cell is equal to 0 if no digits are input, and n+1 if the number n is input. Input is taken at the cell marked "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
add a comment |
Python 2, 118 bytes
import re
n=0
l=input()
o=l.pop(0)
print o
for i in l:(N,x),=re.findall('(d*)(.+)',i);n=int(N or n);o=o[:n]+x;print o
Try it online!
add a comment |
Red, 143 bytes
func[b][a: charset[#"a"-#"z"]u: b/1 n: 0 foreach c b[parse c[copy m to a
p: copy s to end(if p<> c[n: do m]print u: rejoin[copy/part u n s])]]]
Try it online!
add a comment |
Java (JDK), 150 bytes
a->{String p="",s;for(int n=0,i=0;i<a.length;a[i]=p=p.substring(0,n=s.length<1?n:new Short(s[0]))+a[i++].replaceAll("\d",""))s=a[i].split("\D+");}
Try it online!
add a comment |
Jelly, 27 bytes
f€ȯ@V,ɗḟ€ɗØDZẎḊṖḣ2/Ż;"f€Øa
Try it online!
add a comment |
Retina 0.8.2, 69 bytes
+`((d+).*¶)(D)
$1$2$3
d+
$*
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Try it online! Link includes harder test cases. Explanation:
+`((d+).*¶)(D)
$1$2$3
For all lines that begin with letters, copy the number from the previous line, looping until all lines begin with a number.
d+
$*
Convert the number to unary.
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Use balancing groups to replace all 1s with the corresponding letter from the previous line. (This turns out to be slightly golfier than replacing all runs of 1s.)
add a comment |
Perl 5 -p, 45 41 bytes
s:d*:substr($p,0,$l=$&+$l*/^D/):e;$p=$_
Try it online!
Explanation:
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
add a comment |
Groovy, 103 99 bytes
{w=it[0];d=0;it.collect{m=it=~/(d+)(.+)/;i=m.find()?{d=m[0][1] as int;m[0][2]}():it;w=w[0..<d]+i}}
Try it online!
add a comment |
05AB1E, 20 19 17 bytes
õUvyþDõÊi£U}Xyá«=
Try it online or verify all test cases.
Explanation:
õ # 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)
add a comment |
Common Lisp, 181 bytes
(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)))
Try it online!
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
As usual, the long identifers of Common Lisp make it non particularly suitable for PPCG.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "200"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f177803%2fparse-the-bookworm-dictionary-format%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
19 Answers
19
active
oldest
votes
19 Answers
19
active
oldest
votes
active
oldest
votes
active
oldest
votes
Vim, 57 bytes
:%s/a/ &
:%norm +hkyiwjP
:g/d/norm diw-@"yl+P
:%s/ //g
Try it online!
Would<H<Ginstead of the last substitution work?
– Cows quack
yesterday
@cowsquack Unfortunately, no. Every input that doesn't start with a number increases the number of leading spaces so there's no way to guarantee a<solution would unindent enough times.
– DJMcMayhem♦
yesterday
add a comment |
Vim, 57 bytes
:%s/a/ &
:%norm +hkyiwjP
:g/d/norm diw-@"yl+P
:%s/ //g
Try it online!
Would<H<Ginstead of the last substitution work?
– Cows quack
yesterday
@cowsquack Unfortunately, no. Every input that doesn't start with a number increases the number of leading spaces so there's no way to guarantee a<solution would unindent enough times.
– DJMcMayhem♦
yesterday
add a comment |
Vim, 57 bytes
:%s/a/ &
:%norm +hkyiwjP
:g/d/norm diw-@"yl+P
:%s/ //g
Try it online!
Vim, 57 bytes
:%s/a/ &
:%norm +hkyiwjP
:g/d/norm diw-@"yl+P
:%s/ //g
Try it online!
edited Dec 19 at 20:09
answered Dec 19 at 20:02
DJMcMayhem♦
40.9k11145309
40.9k11145309
Would<H<Ginstead of the last substitution work?
– Cows quack
yesterday
@cowsquack Unfortunately, no. Every input that doesn't start with a number increases the number of leading spaces so there's no way to guarantee a<solution would unindent enough times.
– DJMcMayhem♦
yesterday
add a comment |
Would<H<Ginstead of the last substitution work?
– Cows quack
yesterday
@cowsquack Unfortunately, no. Every input that doesn't start with a number increases the number of leading spaces so there's no way to guarantee a<solution would unindent enough times.
– DJMcMayhem♦
yesterday
Would
<H<G instead of the last substitution work?– Cows quack
yesterday
Would
<H<G instead of the last substitution work?– Cows quack
yesterday
@cowsquack Unfortunately, no. Every input that doesn't start with a number increases the number of leading spaces so there's no way to guarantee a
< solution would unindent enough times.– DJMcMayhem♦
yesterday
@cowsquack Unfortunately, no. Every input that doesn't start with a number increases the number of leading spaces so there's no way to guarantee a
< solution would unindent enough times.– DJMcMayhem♦
yesterday
add a comment |
JavaScript (ES6), 66 62 61 bytes
a=>a.map(p=s=>a=a.slice([,x,y]=/(d*)(.*)/.exec(s),p=x||p)+y)
Try it online!
Commented
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()
add a comment |
JavaScript (ES6), 66 62 61 bytes
a=>a.map(p=s=>a=a.slice([,x,y]=/(d*)(.*)/.exec(s),p=x||p)+y)
Try it online!
Commented
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()
add a comment |
JavaScript (ES6), 66 62 61 bytes
a=>a.map(p=s=>a=a.slice([,x,y]=/(d*)(.*)/.exec(s),p=x||p)+y)
Try it online!
Commented
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()
JavaScript (ES6), 66 62 61 bytes
a=>a.map(p=s=>a=a.slice([,x,y]=/(d*)(.*)/.exec(s),p=x||p)+y)
Try it online!
Commented
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()
edited Dec 20 at 10:33
answered Dec 19 at 20:11
Arnauld
72.3k689303
72.3k689303
add a comment |
add a comment |
Perl 6, 50 48 bytes
-2 bytes thanks to nwellnhof
{my$l;.map:{$!=S[d*]=substr $!,0,$l [R||]=~$/}}
Try it online!
A port of Arnauld's solution. Man, that R|| trick was a rollercoaster from 'I think this could be possible', to 'nah, it's impossible', to 'kinda maybe possible' and finally 'aha!'
Explanation:
{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
The $l [R||]=~$/ part roughly translates to $l= ~$/||+$l but... it has the same amount of bytes :(. Originally, it saved bytes using an anonymous variable so the my$l was gone but that doesn't work since the scope is now the substitution, not the map codeblock. Oh well. Anyways, R is the reverse metaoperator, so it reverses the arguments of ||, so the $l variable ends up being assigned the new number (~$/) if it exists, otherwise itself again.
It could be 47 bytes if Perl 6 didn't throw a kinda redundant compiler error for =~.
add a comment |
Perl 6, 50 48 bytes
-2 bytes thanks to nwellnhof
{my$l;.map:{$!=S[d*]=substr $!,0,$l [R||]=~$/}}
Try it online!
A port of Arnauld's solution. Man, that R|| trick was a rollercoaster from 'I think this could be possible', to 'nah, it's impossible', to 'kinda maybe possible' and finally 'aha!'
Explanation:
{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
The $l [R||]=~$/ part roughly translates to $l= ~$/||+$l but... it has the same amount of bytes :(. Originally, it saved bytes using an anonymous variable so the my$l was gone but that doesn't work since the scope is now the substitution, not the map codeblock. Oh well. Anyways, R is the reverse metaoperator, so it reverses the arguments of ||, so the $l variable ends up being assigned the new number (~$/) if it exists, otherwise itself again.
It could be 47 bytes if Perl 6 didn't throw a kinda redundant compiler error for =~.
add a comment |
Perl 6, 50 48 bytes
-2 bytes thanks to nwellnhof
{my$l;.map:{$!=S[d*]=substr $!,0,$l [R||]=~$/}}
Try it online!
A port of Arnauld's solution. Man, that R|| trick was a rollercoaster from 'I think this could be possible', to 'nah, it's impossible', to 'kinda maybe possible' and finally 'aha!'
Explanation:
{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
The $l [R||]=~$/ part roughly translates to $l= ~$/||+$l but... it has the same amount of bytes :(. Originally, it saved bytes using an anonymous variable so the my$l was gone but that doesn't work since the scope is now the substitution, not the map codeblock. Oh well. Anyways, R is the reverse metaoperator, so it reverses the arguments of ||, so the $l variable ends up being assigned the new number (~$/) if it exists, otherwise itself again.
It could be 47 bytes if Perl 6 didn't throw a kinda redundant compiler error for =~.
Perl 6, 50 48 bytes
-2 bytes thanks to nwellnhof
{my$l;.map:{$!=S[d*]=substr $!,0,$l [R||]=~$/}}
Try it online!
A port of Arnauld's solution. Man, that R|| trick was a rollercoaster from 'I think this could be possible', to 'nah, it's impossible', to 'kinda maybe possible' and finally 'aha!'
Explanation:
{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
The $l [R||]=~$/ part roughly translates to $l= ~$/||+$l but... it has the same amount of bytes :(. Originally, it saved bytes using an anonymous variable so the my$l was gone but that doesn't work since the scope is now the substitution, not the map codeblock. Oh well. Anyways, R is the reverse metaoperator, so it reverses the arguments of ||, so the $l variable ends up being assigned the new number (~$/) if it exists, otherwise itself again.
It could be 47 bytes if Perl 6 didn't throw a kinda redundant compiler error for =~.
edited Dec 20 at 13:14
answered Dec 20 at 0:33
Jo King
20.7k246109
20.7k246109
add a comment |
add a comment |
Ruby, 49 45 43 bytes
$0=$_=$0[/.{0#{p=$_[/d+/]||p}}/]+$_[/D+/]
Try it online!
Explanation
$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 $_
add a comment |
Ruby, 49 45 43 bytes
$0=$_=$0[/.{0#{p=$_[/d+/]||p}}/]+$_[/D+/]
Try it online!
Explanation
$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 $_
add a comment |
Ruby, 49 45 43 bytes
$0=$_=$0[/.{0#{p=$_[/d+/]||p}}/]+$_[/D+/]
Try it online!
Explanation
$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 $_
Ruby, 49 45 43 bytes
$0=$_=$0[/.{0#{p=$_[/d+/]||p}}/]+$_[/D+/]
Try it online!
Explanation
$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 $_
edited Dec 20 at 15:14
answered Dec 20 at 8:40
Kirill L.
3,6451318
3,6451318
add a comment |
add a comment |
Haskell, 82 81 bytes
tail.map concat.scanl p["",""]
p[n,l]a|[(i,r)]<-reads a=[take i$n++l,r]|1<2=[n,a]
Takes and returns a list of strings.
Try it online!
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.
Edit: -1 byte thanks to @Nitrodon.
1
Contrary to usual Haskell golfing wisdom, you can actually save one byte here by not defining the helper function as an infix operator.
– Nitrodon
20 hours ago
@Nitrodon: well spotted! Thanks!
– nimi
14 hours ago
add a comment |
Haskell, 82 81 bytes
tail.map concat.scanl p["",""]
p[n,l]a|[(i,r)]<-reads a=[take i$n++l,r]|1<2=[n,a]
Takes and returns a list of strings.
Try it online!
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.
Edit: -1 byte thanks to @Nitrodon.
1
Contrary to usual Haskell golfing wisdom, you can actually save one byte here by not defining the helper function as an infix operator.
– Nitrodon
20 hours ago
@Nitrodon: well spotted! Thanks!
– nimi
14 hours ago
add a comment |
Haskell, 82 81 bytes
tail.map concat.scanl p["",""]
p[n,l]a|[(i,r)]<-reads a=[take i$n++l,r]|1<2=[n,a]
Takes and returns a list of strings.
Try it online!
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.
Edit: -1 byte thanks to @Nitrodon.
Haskell, 82 81 bytes
tail.map concat.scanl p["",""]
p[n,l]a|[(i,r)]<-reads a=[take i$n++l,r]|1<2=[n,a]
Takes and returns a list of strings.
Try it online!
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.
Edit: -1 byte thanks to @Nitrodon.
edited 14 hours ago
answered Dec 19 at 22:31
nimi
31.2k32085
31.2k32085
1
Contrary to usual Haskell golfing wisdom, you can actually save one byte here by not defining the helper function as an infix operator.
– Nitrodon
20 hours ago
@Nitrodon: well spotted! Thanks!
– nimi
14 hours ago
add a comment |
1
Contrary to usual Haskell golfing wisdom, you can actually save one byte here by not defining the helper function as an infix operator.
– Nitrodon
20 hours ago
@Nitrodon: well spotted! Thanks!
– nimi
14 hours ago
1
1
Contrary to usual Haskell golfing wisdom, you can actually save one byte here by not defining the helper function as an infix operator.
– Nitrodon
20 hours ago
Contrary to usual Haskell golfing wisdom, you can actually save one byte here by not defining the helper function as an infix operator.
– Nitrodon
20 hours ago
@Nitrodon: well spotted! Thanks!
– nimi
14 hours ago
@Nitrodon: well spotted! Thanks!
– nimi
14 hours ago
add a comment |
Japt, 19 18 17 bytes
Initially inspired by Arnauld's JS solution.
;£=¯V=XkB ªV +XoB
Try it
: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
add a comment |
Japt, 19 18 17 bytes
Initially inspired by Arnauld's JS solution.
;£=¯V=XkB ªV +XoB
Try it
: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
add a comment |
Japt, 19 18 17 bytes
Initially inspired by Arnauld's JS solution.
;£=¯V=XkB ªV +XoB
Try it
: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
Japt, 19 18 17 bytes
Initially inspired by Arnauld's JS solution.
;£=¯V=XkB ªV +XoB
Try it
: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
edited Dec 20 at 9:17
answered Dec 19 at 23:00
Shaggy
18.9k21666
18.9k21666
add a comment |
add a comment |
Python 3.6+, 172 195 156 123 122 121 104 bytes
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
- -12 bytes thanks to Bubbler
- -5 bytes thanks to Dennis
Try it online!
Explanation
I caved, and used Regular Expressions. This saved at least 17 bytes. :
t=re.match("d*",s)[0]
When the string doesn't begin with a digit at all, the length of this string will be 0. This means that:
n=int(t or n)
will be n if t is empty, and int(t) otherwise.
w=w[:n]+s[len(t):]
removes the number that the regular expression found from s (if there's no number found, it'll remove 0 characters, leaving s untruncated) and replaces all but the first n characters of the previous word with the current word fragment; and:
yield w
outputs the current word.
add a comment |
Python 3.6+, 172 195 156 123 122 121 104 bytes
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
- -12 bytes thanks to Bubbler
- -5 bytes thanks to Dennis
Try it online!
Explanation
I caved, and used Regular Expressions. This saved at least 17 bytes. :
t=re.match("d*",s)[0]
When the string doesn't begin with a digit at all, the length of this string will be 0. This means that:
n=int(t or n)
will be n if t is empty, and int(t) otherwise.
w=w[:n]+s[len(t):]
removes the number that the regular expression found from s (if there's no number found, it'll remove 0 characters, leaving s untruncated) and replaces all but the first n characters of the previous word with the current word fragment; and:
yield w
outputs the current word.
add a comment |
Python 3.6+, 172 195 156 123 122 121 104 bytes
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
- -12 bytes thanks to Bubbler
- -5 bytes thanks to Dennis
Try it online!
Explanation
I caved, and used Regular Expressions. This saved at least 17 bytes. :
t=re.match("d*",s)[0]
When the string doesn't begin with a digit at all, the length of this string will be 0. This means that:
n=int(t or n)
will be n if t is empty, and int(t) otherwise.
w=w[:n]+s[len(t):]
removes the number that the regular expression found from s (if there's no number found, it'll remove 0 characters, leaving s untruncated) and replaces all but the first n characters of the previous word with the current word fragment; and:
yield w
outputs the current word.
Python 3.6+, 172 195 156 123 122 121 104 bytes
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
- -12 bytes thanks to Bubbler
- -5 bytes thanks to Dennis
Try it online!
Explanation
I caved, and used Regular Expressions. This saved at least 17 bytes. :
t=re.match("d*",s)[0]
When the string doesn't begin with a digit at all, the length of this string will be 0. This means that:
n=int(t or n)
will be n if t is empty, and int(t) otherwise.
w=w[:n]+s[len(t):]
removes the number that the regular expression found from s (if there's no number found, it'll remove 0 characters, leaving s untruncated) and replaces all but the first n characters of the previous word with the current word fragment; and:
yield w
outputs the current word.
edited Dec 19 at 23:26
answered Dec 19 at 20:00
wizzwizz4
1,1871035
1,1871035
add a comment |
add a comment |
Jelly, 16 bytes
⁹fØDVo©®⁸ḣ;ḟØDµ
Try it online!
How it works
⁹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.
add a comment |
Jelly, 16 bytes
⁹fØDVo©®⁸ḣ;ḟØDµ
Try it online!
How it works
⁹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.
add a comment |
Jelly, 16 bytes
⁹fØDVo©®⁸ḣ;ḟØDµ
Try it online!
How it works
⁹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.
Jelly, 16 bytes
⁹fØDVo©®⁸ḣ;ḟØDµ
Try it online!
How it works
⁹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.
edited Dec 20 at 3:35
answered Dec 20 at 0:23
Dennis♦
186k32295735
186k32295735
add a comment |
add a comment |
C, 65 57 bytes
n;f(){char c[99];while(scanf("%d",&n),gets(c+n))puts(c);}
Try it online!
Explanation:
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. */
New contributor
Dexter CD is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
C, 65 57 bytes
n;f(){char c[99];while(scanf("%d",&n),gets(c+n))puts(c);}
Try it online!
Explanation:
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. */
New contributor
Dexter CD is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
C, 65 57 bytes
n;f(){char c[99];while(scanf("%d",&n),gets(c+n))puts(c);}
Try it online!
Explanation:
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. */
New contributor
Dexter CD is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
C, 65 57 bytes
n;f(){char c[99];while(scanf("%d",&n),gets(c+n))puts(c);}
Try it online!
Explanation:
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. */
New contributor
Dexter CD is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
edited 2 days ago
New contributor
Dexter CD is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
answered Dec 20 at 19:17
Dexter CD
213
213
New contributor
Dexter CD is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
New contributor
Dexter CD is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
Dexter CD is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
add a comment |
add a comment |
brainfuck, 201 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,.[->+>+<<]>>----------]<[<<]>-<<<,]
Try it online!
Requires a trailing newline at the end of the input. A version without this requirement is 6 bytes longer:
brainfuck, 207 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,[->+>+<<]>>[----------<.<]>>]<[<<]>-<<<,]
Try it online!
Both versions assume all numbers are strictly less than 255.
Explanation
The tape is laid out as follows:
tempinputcopy 85 0 inputcopy number 1 a 1 a 1 r 1 d 0 w 0 o 0 l 0 f 0 ...
The "number" cell is equal to 0 if no digits are input, and n+1 if the number n is input. Input is taken at the cell marked "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
add a comment |
brainfuck, 201 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,.[->+>+<<]>>----------]<[<<]>-<<<,]
Try it online!
Requires a trailing newline at the end of the input. A version without this requirement is 6 bytes longer:
brainfuck, 207 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,[->+>+<<]>>[----------<.<]>>]<[<<]>-<<<,]
Try it online!
Both versions assume all numbers are strictly less than 255.
Explanation
The tape is laid out as follows:
tempinputcopy 85 0 inputcopy number 1 a 1 a 1 r 1 d 0 w 0 o 0 l 0 f 0 ...
The "number" cell is equal to 0 if no digits are input, and n+1 if the number n is input. Input is taken at the cell marked "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
add a comment |
brainfuck, 201 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,.[->+>+<<]>>----------]<[<<]>-<<<,]
Try it online!
Requires a trailing newline at the end of the input. A version without this requirement is 6 bytes longer:
brainfuck, 207 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,[->+>+<<]>>[----------<.<]>>]<[<<]>-<<<,]
Try it online!
Both versions assume all numbers are strictly less than 255.
Explanation
The tape is laid out as follows:
tempinputcopy 85 0 inputcopy number 1 a 1 a 1 r 1 d 0 w 0 o 0 l 0 f 0 ...
The "number" cell is equal to 0 if no digits are input, and n+1 if the number n is input. Input is taken at the cell marked "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
brainfuck, 201 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,.[->+>+<<]>>----------]<[<<]>-<<<,]
Try it online!
Requires a trailing newline at the end of the input. A version without this requirement is 6 bytes longer:
brainfuck, 207 bytes
,[[[-<+>>>+<<]>-[---<+>]<[[-<]>>]<[-]>>[<<,>>>[-[-<++++++++++>]]++++<[->+<]-[----->-<]<]<]>>>[[>>]+[-<<]>>[[>>]+[<<]>>-]]+[>>]<[-]<[<<]>[->[>>]<+<[<<]>]>[>.>]+[>[-]<,[->+>+<<]>>[----------<.<]>>]<[<<]>-<<<,]
Try it online!
Both versions assume all numbers are strictly less than 255.
Explanation
The tape is laid out as follows:
tempinputcopy 85 0 inputcopy number 1 a 1 a 1 r 1 d 0 w 0 o 0 l 0 f 0 ...
The "number" cell is equal to 0 if no digits are input, and n+1 if the number n is input. Input is taken at the cell marked "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
answered 17 hours ago
Nitrodon
6,8411820
6,8411820
add a comment |
add a comment |
Python 2, 118 bytes
import re
n=0
l=input()
o=l.pop(0)
print o
for i in l:(N,x),=re.findall('(d*)(.+)',i);n=int(N or n);o=o[:n]+x;print o
Try it online!
add a comment |
Python 2, 118 bytes
import re
n=0
l=input()
o=l.pop(0)
print o
for i in l:(N,x),=re.findall('(d*)(.+)',i);n=int(N or n);o=o[:n]+x;print o
Try it online!
add a comment |
Python 2, 118 bytes
import re
n=0
l=input()
o=l.pop(0)
print o
for i in l:(N,x),=re.findall('(d*)(.+)',i);n=int(N or n);o=o[:n]+x;print o
Try it online!
Python 2, 118 bytes
import re
n=0
l=input()
o=l.pop(0)
print o
for i in l:(N,x),=re.findall('(d*)(.+)',i);n=int(N or n);o=o[:n]+x;print o
Try it online!
answered Dec 19 at 23:18
Erik the Outgolfer
31.3k429102
31.3k429102
add a comment |
add a comment |
Red, 143 bytes
func[b][a: charset[#"a"-#"z"]u: b/1 n: 0 foreach c b[parse c[copy m to a
p: copy s to end(if p<> c[n: do m]print u: rejoin[copy/part u n s])]]]
Try it online!
add a comment |
Red, 143 bytes
func[b][a: charset[#"a"-#"z"]u: b/1 n: 0 foreach c b[parse c[copy m to a
p: copy s to end(if p<> c[n: do m]print u: rejoin[copy/part u n s])]]]
Try it online!
add a comment |
Red, 143 bytes
func[b][a: charset[#"a"-#"z"]u: b/1 n: 0 foreach c b[parse c[copy m to a
p: copy s to end(if p<> c[n: do m]print u: rejoin[copy/part u n s])]]]
Try it online!
Red, 143 bytes
func[b][a: charset[#"a"-#"z"]u: b/1 n: 0 foreach c b[parse c[copy m to a
p: copy s to end(if p<> c[n: do m]print u: rejoin[copy/part u n s])]]]
Try it online!
edited Dec 20 at 13:24
answered Dec 20 at 13:09
Galen Ivanov
6,29711032
6,29711032
add a comment |
add a comment |
Java (JDK), 150 bytes
a->{String p="",s;for(int n=0,i=0;i<a.length;a[i]=p=p.substring(0,n=s.length<1?n:new Short(s[0]))+a[i++].replaceAll("\d",""))s=a[i].split("\D+");}
Try it online!
add a comment |
Java (JDK), 150 bytes
a->{String p="",s;for(int n=0,i=0;i<a.length;a[i]=p=p.substring(0,n=s.length<1?n:new Short(s[0]))+a[i++].replaceAll("\d",""))s=a[i].split("\D+");}
Try it online!
add a comment |
Java (JDK), 150 bytes
a->{String p="",s;for(int n=0,i=0;i<a.length;a[i]=p=p.substring(0,n=s.length<1?n:new Short(s[0]))+a[i++].replaceAll("\d",""))s=a[i].split("\D+");}
Try it online!
Java (JDK), 150 bytes
a->{String p="",s;for(int n=0,i=0;i<a.length;a[i]=p=p.substring(0,n=s.length<1?n:new Short(s[0]))+a[i++].replaceAll("\d",""))s=a[i].split("\D+");}
Try it online!
answered Dec 20 at 18:51
Olivier Grégoire
8,76711843
8,76711843
add a comment |
add a comment |
Jelly, 27 bytes
f€ȯ@V,ɗḟ€ɗØDZẎḊṖḣ2/Ż;"f€Øa
Try it online!
add a comment |
Jelly, 27 bytes
f€ȯ@V,ɗḟ€ɗØDZẎḊṖḣ2/Ż;"f€Øa
Try it online!
add a comment |
Jelly, 27 bytes
f€ȯ@V,ɗḟ€ɗØDZẎḊṖḣ2/Ż;"f€Øa
Try it online!
Jelly, 27 bytes
f€ȯ@V,ɗḟ€ɗØDZẎḊṖḣ2/Ż;"f€Øa
Try it online!
answered Dec 19 at 20:10
Erik the Outgolfer
31.3k429102
31.3k429102
add a comment |
add a comment |
Retina 0.8.2, 69 bytes
+`((d+).*¶)(D)
$1$2$3
d+
$*
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Try it online! Link includes harder test cases. Explanation:
+`((d+).*¶)(D)
$1$2$3
For all lines that begin with letters, copy the number from the previous line, looping until all lines begin with a number.
d+
$*
Convert the number to unary.
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Use balancing groups to replace all 1s with the corresponding letter from the previous line. (This turns out to be slightly golfier than replacing all runs of 1s.)
add a comment |
Retina 0.8.2, 69 bytes
+`((d+).*¶)(D)
$1$2$3
d+
$*
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Try it online! Link includes harder test cases. Explanation:
+`((d+).*¶)(D)
$1$2$3
For all lines that begin with letters, copy the number from the previous line, looping until all lines begin with a number.
d+
$*
Convert the number to unary.
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Use balancing groups to replace all 1s with the corresponding letter from the previous line. (This turns out to be slightly golfier than replacing all runs of 1s.)
add a comment |
Retina 0.8.2, 69 bytes
+`((d+).*¶)(D)
$1$2$3
d+
$*
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Try it online! Link includes harder test cases. Explanation:
+`((d+).*¶)(D)
$1$2$3
For all lines that begin with letters, copy the number from the previous line, looping until all lines begin with a number.
d+
$*
Convert the number to unary.
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Use balancing groups to replace all 1s with the corresponding letter from the previous line. (This turns out to be slightly golfier than replacing all runs of 1s.)
Retina 0.8.2, 69 bytes
+`((d+).*¶)(D)
$1$2$3
d+
$*
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Try it online! Link includes harder test cases. Explanation:
+`((d+).*¶)(D)
$1$2$3
For all lines that begin with letters, copy the number from the previous line, looping until all lines begin with a number.
d+
$*
Convert the number to unary.
+m`^((.)*(.).*¶(?<-2>.)*)(?(2)$)1
$1$3
Use balancing groups to replace all 1s with the corresponding letter from the previous line. (This turns out to be slightly golfier than replacing all runs of 1s.)
answered Dec 20 at 10:47
Neil
79.2k744177
79.2k744177
add a comment |
add a comment |
Perl 5 -p, 45 41 bytes
s:d*:substr($p,0,$l=$&+$l*/^D/):e;$p=$_
Try it online!
Explanation:
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
add a comment |
Perl 5 -p, 45 41 bytes
s:d*:substr($p,0,$l=$&+$l*/^D/):e;$p=$_
Try it online!
Explanation:
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
add a comment |
Perl 5 -p, 45 41 bytes
s:d*:substr($p,0,$l=$&+$l*/^D/):e;$p=$_
Try it online!
Explanation:
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
Perl 5 -p, 45 41 bytes
s:d*:substr($p,0,$l=$&+$l*/^D/):e;$p=$_
Try it online!
Explanation:
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
edited Dec 20 at 17:19
answered Dec 20 at 16:16
wastl
2,074425
2,074425
add a comment |
add a comment |
Groovy, 103 99 bytes
{w=it[0];d=0;it.collect{m=it=~/(d+)(.+)/;i=m.find()?{d=m[0][1] as int;m[0][2]}():it;w=w[0..<d]+i}}
Try it online!
add a comment |
Groovy, 103 99 bytes
{w=it[0];d=0;it.collect{m=it=~/(d+)(.+)/;i=m.find()?{d=m[0][1] as int;m[0][2]}():it;w=w[0..<d]+i}}
Try it online!
add a comment |
Groovy, 103 99 bytes
{w=it[0];d=0;it.collect{m=it=~/(d+)(.+)/;i=m.find()?{d=m[0][1] as int;m[0][2]}():it;w=w[0..<d]+i}}
Try it online!
Groovy, 103 99 bytes
{w=it[0];d=0;it.collect{m=it=~/(d+)(.+)/;i=m.find()?{d=m[0][1] as int;m[0][2]}():it;w=w[0..<d]+i}}
Try it online!
edited yesterday
answered yesterday
GolfIsAGoodWalkSpoilt
1012
1012
add a comment |
add a comment |
05AB1E, 20 19 17 bytes
õUvyþDõÊi£U}Xyá«=
Try it online or verify all test cases.
Explanation:
õ # 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)
add a comment |
05AB1E, 20 19 17 bytes
õUvyþDõÊi£U}Xyá«=
Try it online or verify all test cases.
Explanation:
õ # 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)
add a comment |
05AB1E, 20 19 17 bytes
õUvyþDõÊi£U}Xyá«=
Try it online or verify all test cases.
Explanation:
õ # 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)
05AB1E, 20 19 17 bytes
õUvyþDõÊi£U}Xyá«=
Try it online or verify all test cases.
Explanation:
õ # 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)
edited yesterday
answered yesterday
Kevin Cruijssen
35.6k554186
35.6k554186
add a comment |
add a comment |
Common Lisp, 181 bytes
(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)))
Try it online!
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
As usual, the long identifers of Common Lisp make it non particularly suitable for PPCG.
add a comment |
Common Lisp, 181 bytes
(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)))
Try it online!
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
As usual, the long identifers of Common Lisp make it non particularly suitable for PPCG.
add a comment |
Common Lisp, 181 bytes
(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)))
Try it online!
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
As usual, the long identifers of Common Lisp make it non particularly suitable for PPCG.
Common Lisp, 181 bytes
(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)))
Try it online!
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
As usual, the long identifers of Common Lisp make it non particularly suitable for PPCG.
answered yesterday
Renzo
1,640516
1,640516
add a comment |
add a comment |
If this is an answer to a challenge…
…Be sure to follow the challenge specification. However, please refrain from exploiting obvious loopholes. Answers abusing any of the standard loopholes are considered invalid. If you think a specification is unclear or underspecified, comment on the question instead.
…Try to optimize your score. For instance, answers to code-golf challenges should attempt to be as short as possible. You can always include a readable version of the code in addition to the competitive one.
Explanations of your answer make it more interesting to read and are very much encouraged.…Include a short header which indicates the language(s) of your code and its score, as defined by the challenge.
More generally…
…Please make sure to answer the question and provide sufficient detail.
…Avoid asking for help, clarification or responding to other answers (use comments instead).
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodegolf.stackexchange.com%2fquestions%2f177803%2fparse-the-bookworm-dictionary-format%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Is there a possibility that there will not be a number in the second line? Also, can we assume that no number except
0will have leading0s?– Erik the Outgolfer
Dec 19 at 19:43
@EriktheOutgolfer Yes, that is possible; I've added that to the test case. And yes, you can assume that (as well as that the number won't be greater than the length of the previous word).
– Doorknob♦
Dec 19 at 19:46
9
That's a cute compression format :]
– Poke
Dec 19 at 20:19
1
The
locateprogram uses this type of encoding on pathnames.– Dan D.
Dec 19 at 21:24
I wrote this program for my actual use, about 15 years ago. Unfortunately I don't think I have the source anymore...
– hobbs
Dec 20 at 1:24