| Bytes | Lang | Time | Link |
|---|---|---|---|
| 025 | Pip | 210914T171918Z | DLosc |
| 035 | Charcoal | 211001T142705Z | Neil |
| 056 | Python 3.8 prerelease | 210913T024611Z | wasif |
| 062 | jq | 210916T002107Z | DLosc |
| 060 | PowerShell Core | 210913T013352Z | Julian |
| 019 | 05AB1E | 210913T102359Z | Kevin Cr |
| 056 | Python 3 | 210913T094143Z | tsh |
| 048 | JavaScript Node.js | 210913T091443Z | tsh |
| 029 | Jelly | 210912T190602Z | Jonathan |
Pip, 27 25 bytes
W#Sb&a~@b.sbPB$'~KXW@>:2b
The tag definitions and the initial word are taken as command-line arguments. Each definition is given as alphabet symbol + space + string, and definitions are separated by any non-space non-alphanumeric symbol. For example:
a bc;b a;c aaa
This will need to be quoted so the command-line treats it as a single argument.
Explanation
W#Sb&a~@b.sbPB$'~KXW@>:2b
; a, b are cmdline args; s is space; XW is `\w` (implicit)
W ; While
# ; length of
Sb ; longest suffix of b (the current word)
; is nonzero (i.e. length of b is at least 2)
& ; and
@b ; first character of b
.s ; concatenated to a space
a~ ; matches somewhere in a (the definitions)
; do:
bPB ; Push this string onto the end of b:
$' ; In the part of a after the match,
~ ; find the first match of:
XW ; Word character: \w
K ; with Kleene star operator: \w*
; i.e. the definition of the current character
@>:2 ; Set b to all but the first two characters of b
b ; After the loop, output the final value of b
Charcoal, 35 bytes
SθWS⊞υιW∧⊖LθΦυ⁼§θ⁰§κ⁰≔⭆⟦θ⊟ι⟧Φκ›ν¹θθ
Try it online! Link is to verbose version of code. Takes input as the string to be transformed followed by a list of transformations in the form symbol:stringofsymbols. Explanation:
Sθ
Input the string to be transformed.
WS⊞υι
Input the list of transformations.
W∧⊖LθΦυ⁼§θ⁰§κ⁰
Repeat while the string is longer than a single character and the first character is the first character of one of the transformations.
≔⭆⟦θ⊟ι⟧Φκ›ν¹θθ
Remove the first two characters from the string and the matching transformation and concatenate the result.
Python 3.8 (pre-release), 56 bytes
f=lambda a,d:a[:len(a)>1]in d and f(a[2:]+d[a[0]],d)or a
-4 thanks to @JonathanAllan
-3 thanks to @Neil
Normal recursive approach
Takes a string and a dictionary of transformations
jq, 62 bytes
.P as$P|.w|until(length<2//(.[:1]|in($P)|not);.[2:]+$P[.[:1]])
Takes input as a JSON object with keys P and w. The value of P is an object whose keys are alphabet symbols and whose values are their associated strings. The value of w is the initial word. Try it online!
Explanation
.P as $P | Store the P mapping in the variable $P
.w | The rest of the program will manipulate the input word
until ( Until this condition is true...
length < 2 The length of the word is less than 2
// ( or:
.[:1] | The first character of the word
in($P) | Is a key in $P
not) Make that "is NOT a key in $P"
; ...update the word to be the following:
.[2:] + The word minus its first two characters, plus
$P[ the value in $P at this key:
.[:1] The first character in the word
])
When the loop exits, return the final value of the word
PowerShell Core, 68 60 bytes
for($a,$d=$args;$a[1]-and($u=$d[$a[0]])){$a=$a+$u|% Su* 2}$a
Takes two parameters:
- the string to process
- a dictionary of char / strings
Explanations
for($a,$d=$args; # Sets the variables $a, the string to process and $d the dictionary of transformations
$a[1]-and # While there is more than 1 character left
($u=$d[$a[0]])){ # And there is a transformation for the first character of $a, store the transformation in $u
$a=$a+$u|% Su* 2} # Concatenates $a and $u and takes all the characters from the second position
$a # return $a when it is 1 char long or we hit a halting symbol
-2 bytes thanks to wasif!
-6 bytes thanks to Zaelin Goodman!
05AB1E, 20 19 bytes
[Dg#¬UI.ΔнXQ}Ä#諦¦
Inputs in the order string, map, where the map are key-value pairs as space-delimited strings.
Try it online or verify both test cases.
Explanation:
[ # Start an infinite loop:
D # Duplicate the current string (or the implicit first input-string in
# the first iteration)
g # Pop and get its length
# # If its length is 1: stop the infinite loop
# (after which the duplicated string is output implicitly as result)
¬ # Else: get the first character (without popping the string)
U # Pop and store this head in variable `X`
I # Push the second input-list of pairs
.Δ # Find the first which is truthy for:
н # Where its first item (the key)
XQ # Equals head `X`
} # Close the find-first (this will result in -1 if none were found)
Ä # Get the absolute value (no-op for a pair of strings)
# # If this is 1: stop the infinite loop
# (after which the string is output implicitly as result)
# # Else: the `#` will act as a 'split-on-spaces' instead
θ # Pop and leave last item (the value)
« # Append it to the string
¦¦ # And remove the first two characters
Python 3, 56 bytes
def f(a,d):
try:x,y,*z=a;a[:]=*z,*d[x];f(a,d)
except:0
This function take input as a list of chars, and a dict of char to list of chars. And it returns by modify a in-place.
And if terminating the function by an exception is allowed, it could be even shorter:
Python 3, 40 bytes
def f(a,d):x,y,*z=a;a[:]=*z,*d[x];f(a,d)
Jelly, 29 bytes
Feels clunky to me at present.
ZḢiȧị¥⁸0ị
;1ịç@ɗ¥⁹ḊḊʋḊȦ$¡ƬẠƇṪ
A dyadic Link that accepts the initial word on the left and the production rules (\$P\$) on the right and yields the result.
Try it online! (Each production rule is [chr, [chr, ...]], but a list of these cannot be passed as an argument to a program so the footer translates them from a list of [[chr], [chr, ...]])
How?
ZḢiȧị¥⁸0ị - Link 1, get new characters (or zero): rules, R; character, C
Z - transpose (R)
Ḣ - head -> alphabet
i - first 1-indexed index of (C) in (alphabet) or, when C=Halt, zero
¥⁸ - last two links as a dyad, f(I=that, R)
ị - (I) index into (R)
ȧ - (I) logical AND (that) -> relevant rule or zero
0ị - tail -> new characters or zero
;1ịç@ɗ¥⁹ḊḊʋḊȦ$¡ƬẠƇṪ - Link: initial word, W; rules, R
Ƭ - collect up, starting with W, while no duplicates found with:
¡ - repeat...
$ - ...number of times: last two links as a monad, f(current):
Ḋ - dequeue
Ȧ - has elements and none are zero (found when processing a halt)
ʋ - ...what: last four links as a dyad, f(current, R)
⁹ - right argument, R
¥ - last two links as a dyad, f(current, R)
ɗ - last three links as a dyad, f(current, R)
1 - one
ị - index into (current) -> head character
ç@ - call Link 1 as a dyad, f(R, character)
; - (current) concatenate (that)
Ḋ - dequeue
Ḋ - dequeue
Ƈ - keep those for which:
Ạ - all truthy (are not the result of processing a halt)
Ṫ - tail