Code Golf Asked by Kevin Cruijssen on December 10, 2021
Inspired by the Puzzling-stackexchange post with the same name, which I’ve answered four years ago:
Can you create a perfectly valid English sentence, which makes perfect sense, but which contains the word "and" in it, five times consecutively in a row ?
"Something-or-other and and and and and something-else."
Given a string input, replace all occurrences of the word ‘and’ with five times that word; three in lowercase, interleaved with two of the original cased word.
Some examples:
AND
would become and AND and AND and
and
would become and and and and and
AnD
would become and AnD and AnD and
There is one catch however (restricted-source):
You’re not allowed to use the characters aAnNdD
in your source code. Any other character is still allowed, even if it’s the unicode value of these letters, only these six characters themselves are banned.
aAnNdD
.and
if it isn’t a standalone word (see test cases with stand
, band
, and Anderson
)Input: "Toys And Puzzles"
Output: "Toys and And and And and Puzzles"
Input: "and"
Output: "and and and and and"
Input: "AND and anD"
Output: "and AND and AND and and and and and and and anD and anD and"
Input: "Please stand over there and watch" # note that the "and" in "stand" isn't changed
Output: "Please stand over there and and and and and watch"
Input: "The crowd loves this band" # note that the "and" in "band" isn't changed
Output: "The crowd loves this band"
Input: "Toys and And and And and Puzzles"
Output: "Toys and and and and and and And and And and and and and and and and And and And and and and and and and Puzzles"
Input: "Mr Anderson went for a walk and found a five dollar bill" # note that the "And" in "Anderson" isn't changed
Output: "Mr Anderson went for a walk and and and and and found a five dollar bill"
b="97110100"_G["lo97100"]('pri110t(97rg[1]:gsub("%w+",fu110ctio110(s)retur110 s:lower()==b '..b..' (b.." "..s.." "):rep(2)..b e110100))')()
b
is a string which is equal to "and" via ASCII escape codes.
_G
in Lua is the "global environment table", the data structure containing all global variables. We can index this with a string, which can contain ASCII codes for the forbidden letters.
load()
returns a function from the string passed to it (which we immediately call). Again, ASCII codes are used here for forbidden characters.
arg
is the command-line arguments table
gsub()
is a Global SUBstitution function, it takes a pattern (in this case a sequence of 1 or more alphanumeric characters) and replaces it according to the second parameter, in this case an anonymous function which it calls for every match.
and
is a boolean operator which return the right-hand-side of the operation or false
.
rep()
is a string repetition function.
-- Match Every Word, Replacing Any "and"s
print(arg[1]:gsub("%w+",function(s)
return s:lower() == "and" and ("and "..s.." "):rep(2).."and"
end))
Answered by Benrob0329 on December 10, 2021
-4 bytes thanks to att!
Stri.6egRepl.61ce[a:Regul.61rExpressio.6e["(?i)\b"<>#<>"\b"]:>Stri.6egRiffle@{#,a,#,a,#}]&@".61.6e.64"
Try it online! An expression that evaluates to a function. Uses the standard regex (?i)bandb
. For reference, the shortest equivalent function that doesn't use a regex is 118 bytes:
Stri.6egRepl.61ce[a=WordBou.6ed.61ry;a~~b:#~~a:>Stri.6egRiffle@{#,b,#,b,#},Ig.6eoreC.61se->1>0]&@".61.6e.64"
Answered by LegionMammal978 on December 10, 2021
s/<c!c.c$>/L&E & L&E & L&/Ig
"and" is written escaped as c!c.c$
. cx
means take the character x
, convert it to upper case if it is a lower case letter, and then flip bit 6. The surrounding <
and >
mean word boundaries. &
corresponds to the matched string. L
switches to lowercase, and E
switches back. The I
modifier means ignore case when matching. The g
modifier means replace all matches, not just the first.
Answered by RobertR on December 10, 2021
å╔é╩⌐╬²ßxæ╬:Ö5ò▌@ Θ5YS₧Ñπε
I knew packed stax mutation was good for something.
Saved 6 bytes thanks to an anonymous donor.
Answered by Joshua on December 10, 2021
(7⍴'b',⎕ucs 65 78 68)⎕R(15⍴'l& & ')⍠1
Golfed ... a lot of bytes thanks to @Adám
Answered by Ada on December 10, 2021
k=iⁿput().split();o=[]
while k:w,*k=k;o+=([w],[x:=w.lower(),w,x,w,x])["x61x6ex64"==x]
priⁿt(*o)
-2 bytes inspired by this answer from Luis Mendo.
exec('priⁿt(*sum([([x:=w.lower(),w,x,w,x],[w])["x61x6ex64"!=x]for w ix6e iⁿput().split()],[]))')
Deobfuscated Code:
priⁿt(*sum([([x:=w.lower(),w,x,w,x],[w])["and"!=x]for w in iⁿput().split()],[]))
Answered by ovs on December 10, 2021
-3 -3 bytes thanks to ceilingcat
-19 bytes thanks to xibu
L,M,P=543452769;f(s,t)typeof("")s,t;{M=M>>8|*s<<24;t=(M|' '|L<<24)-P?t:memcpy(t-3,(typeof(0)[]){P,M|=1<<29,P,M,P},20)+19;L=M;(*t=*s)&&f(s+1,t+1);}
sizeof(int) == 4
sizeof(int *) >= sizeof(char *)
(I cannot imagine what absurd platform this would be false on, but you never know.)typeof()
provided by the compiler.We step through the input string one character at a time. This character is placed at the top-most byte of M
, shifting the previous characters to the left. This makes it so that M
continuously holds a record of the four current characters. That's this part:
M=M>>8|*s<<24
Next up, we make M
lower-case, and OR our fourth character with the previous character that we had before M
. We compare the whole shebang with our magic number P
, which represents the string "and ". Why ORing with the previous character like that? Well, it will only be true if that character was 0 (as in we are in the beginning of the string) or a space:
(M|' '|L<<24)==P
If this is true, we know we have an "and" to deal with. We make sure the last character of M
is a space and not NUL, and build an anonymous array of integers to copy into target string.
This array is built from noting that the word "and" (and whatever arbitrary case variant we picked out of the source string) will always be followed by a space (except for the last instance) when expanded to its final form, which means a neat four bytes, which happens to be the size of an integer. The string "and " is represented by P
(little-endian makes the string appear reversed when viewed as a number):
M|=1<<29 Make highest byte of M a space
t=memcpy(
t-3 Copy to sightly before target string
,(typeof(0)[]){P,M,P,M,P} Integer array of "and " isotopes
,20)
+19 Increment target string
Why to we copy to three bytes before the current target string? Because we have already copied those bytes before we knew it was an "and". And since this memcpy()
is only ever called when we have found the keyword, we will never copy out of bounds.
The rest is straight-forward:
L=M; Last = Current
(*t=*s)&&f(s+1,t+1) Copy byte and go to next bytes
in strings if not end-of-string
Answered by gastropner on December 10, 2021
-s
, 34 bytesY Jz@[i13 3]{(gPEyLC@gQy?,5o)}Mq^s
Non-regex solution taking advantage of the "letters and spaces only" rule. Partially inspired by Jonathan Allan's Jelly answer.
Y Jz@[i13 3]{(gPEyLC@gQy?,5o)}Mq^s
z is lowercase alphabet; i is 0; o is 1 (implicit)
z@[i13 3] Get the lowercase letters at indices 0, 13, and 3
J Join them into the string "and"
Y Yank that into the variable y
q Read a line of input from stdin
^s Split on spaces
{ }M Map this function:
g The list of arguments: [word]
PEy with y prepended: ["and" word]
( ) Index this list with the following index:
? If
@g the first argument
LC lowercased
Qy equals y
,5 then range(5)
o else 1
Here's what the indexing does: If the word
we're processing is some case-variant of "and"
, we get the first five elements of the list ["and" word]
. With cyclic indexing, this amounts to ["and" word "and" word "and"]
. If the word is some other word, we get the element at index 1, which is just word
.
The result is a (possibly nested) list, which the -s
flag joins on spaces and then autoprints. An example run:
q "Stand aNd watch"
q^s ["Stand" "aNd" "" "watch"]
{ }Mq^s ["Stand" ["and" "aNd" "and" "aNd" "and"] "" "watch"]
Output: Stand and aNd and aNd and watch
Y Jz@[i13 3]qR-:yWR`b`yWR` & `WRy
My initial solution using regex:
Y Jz@[i13 3]qR-:yWR`b`yWR` & `WRy
z is lowercase alphabet; i is 0 (implicit)
z@[i13 3] Get the lowercase letters at indices 0, 13, and 3
J Join them into the string "and"
Y Yank that into the variable y
q Read a line of input from stdin
R In that string, replace
y the string "and"
WR`b` wrapped in the regex `b`: `bandb`
-: with the case-insensitive flag set: `(?i)bandb`
with
y the string "and"
WR` & ` wrapped in the regex ` & `: ` & and & `
WRy wrapped in the string "and": `and & and & and`
(where & in replacement context stands for the
full match)
Autoprint (implicit)
Answered by DLosc on December 10, 2021
q='141156144'
l='=l141mb144141 x:'
exec(f"f{l}x {q} x[0]+((q+x[:5])*2+q+f(x[4:])if' {q} '==x[:5].lower()else f(x[1:]));g{l}f(' '+x+' ')[1:-1]")
Since xnor said it would take imagination I've gone ahead and done a python answer. It is more of a proof of concept than anything else since I am quite rusty on python golf.
I wrote the pretty straightforward code:
q='and'
f=lambda x:x and x[0]+((q+x[:5])*2+q+f(x[4:])if' and '==x[:5].lower()else f(x[1:]))
g=lambda x:f(' '+x+' ')[1:-1]
Which would solve the problem if it were not for the character restriction. Then to get around the restriction I used exec
with escape codes on all the problematic characters.
exec("q='141156144';f=l141mb144141 x:x 141156144 x[0]+((q+x[:5])*2+q+f(x[4:])if' 141156144 '==x[:5].lower()else f(x[1:]));g=l141mb144141 x:f(' '+x+' ')[1:-1]")
And since and
appeared in the original source 3 times, I moved the definition of q
outside the exec and inserted q
in those places to save bytes. I also wrote a substitution for =lambda x:
since it appears twice.
q='141156144'
l='=l141mb144141 x:'
exec(f"f{l}x {q} x[0]+((q+x[:5])*2+q+f(x[4:])if' {q} '==x[:5].lower()else f(x[1:]));g{l}f(' '+x+' ')[1:-1]")
Answered by Grain Ghost on December 10, 2021
r x|_:z:_<-[x..]=z
(#)=elem.r
f(b:t@(c:e:g:h:s))|u<-b:c:e:g:" ",[b,h]<" !",c#"bB",e#"oO",g#"eE",i<-r<$>"`mc"=b:i++u++i++u++i++f(h:s)
f" "=""
f(b:t)=b:f t
g x|_:y<-f$' ':x++" "=y
r
takes a character and returns the next character in ASCII order. That is to say its successor.
Then we use this to make (#)
which takes a character and a list and checks if that character's successor is in the list.
Then we use that to make f
.
Many of the functions I would really like to use from Haskell are missing.
(#)=elem
f(b:t@(c:e:g:h:s))|u<-b:c:e:g:" ",[b,h]<" !",c#"6597",e#"78110",g#"68100",i<-"97110100"=b:i++u++i++u++i++f(h:s)
f" "=""
f(b:t)=b:f t
g x|_:y<-f$' ':x++" "=y
This version forgoes using r
to generate forbidden characters and instead escapes them. Boring but saves 3 bytes.
Answered by Grain Ghost on December 10, 2021
Saved 4 bytes thanks to Dom Hastings!!!
s/bx61x6ex64b/& & &/Ig;s/&/x61x6ex64/g
Swaps all occurances of and
(which is written in escaped hex as x61x6ex64
) in any case surrounded by word boundaries (b
) with: a ampersand (&
), followed by that occurance, another ampersand, that occurance again, and finally a third ampersand. Since all input only contains spaces and letters, any ampersands present are there because of those swaps. So they're all replaced with and
(x61x6ex64
) to complete the process.
Answered by Noodle9 on December 10, 2021
Closing quotes and parens already discounted. It's not pretty, but I found some surprising optimizations.
Input: C1
Cells B1
to B9
(One cell per row).
[SPACE]
=B1&LEFT(RIGHT(TEXT(,"[$-33]MMMM"),4),3)&B1
=UPPER(B2)
=LEFT(B2,2)&RIGHT(B3,3)
=LEFT(B2,3)&RIGHT(B3,2)
=LEFT(B3,3)&RIGHT(B2,2)
=LEFT(B3,2)&RIGHT(B5,3)
=PROPER(B2)
=LEFT(B2,2)&RIGHT(B6,3)
Cells C2
to C9
=SUBSTITUTE(B1&C1&B1,B2,REPT(B2,5))
=SUBSTITUTE(C2,B3,B2&B3&B2&B3&B2)
=SUBSTITUTE(C3,B4,B2&B4&B2&B4&B2)
=SUBSTITUTE(C4,B5,B2&B5&B2&B5&B2)
=SUBSTITUTE(C5,B6,B2&B6&B2&B6&B2)
=SUBSTITUTE(C6,B7,B2&B7&B2&B7&B2)
=SUBSTITUTE(C7,B8,B2&B8&B2&B8&B2)
=TRIM(SUBSTITUTE(C8,B9,B2&B9&B2&B9&B2))
...where C9 is the final output.
TEXT()
creates the text "Phando" (EN January) in Venda, an official language of South Africa. The rest of it extracts the "and" from it and surrounds it with spaces.Answered by Calculuswhiz on December 10, 2021
Work in progress
r`%ß@%b`È3ÇXvÃqXû5}'i
-S
flag)¸cÈv ¶`ß@`Å?5ogX¸iXv:X
¸cÈv ¶`ß@`Å?5ogX¸iXv:X :Implicit input of string
¸ :Split on spaces
c :Map then flatten
È :Passing each X through the following function
v : Lowercase
¶ : Test for equality with
`ß@` : The compressed string "band" ("and" compressed is also 2 bytes but includes the "d")
Å : Slice off the first character
? : If true
5o : Range [0,5)
g : Index (0-based) each into
X¸ : Split X on spaces, converting it to a single element array
i : Prepend
Xv : Lowercase X
:X : Else return X
:Implicit output joined by spaces
Answered by Shaggy on December 10, 2021
"(?i)(\bu0061u006eu0064\b)".r replu0061ceu0041llIu006e(_,m=>{vu0061l x=m+""toLowerCu0061se;s"$x $m "*2+x})
You do need to assign that function to a variable of type String => String
, though, and enable postfix operators (to save 1 byte). This adds 21 more characters.
def f:String=>String="(?i)(\bu0061u006eu0064\b)".r replu0061ceu0041llIu006e(_,m=>{vu0061l x=m group 0 toLowerCu0061se;s"$x $m $x $m $x"})
After Scala 2.13, you need to use backticks around variable names when using unicode escapes, hence Scala 2.12.2.
Prettier version
val f: String => String = s =>
raw"(?i)(bandb)".r.replaceAllIn(s,
m => {
val x = m.group(0).toLowerCase
s"$x $m $x $m $x"
})
Answered by HALP DA MODS 11'D MY NAM on December 10, 2021
≔“1“$K”η⪫E⪪S ⎇⁼↧ιη⪫⟦ηιηιη⟧ ι
Try it online! No verbose mode because it won't "compress" the string for me. Explanation:
≔“1“$K”η
Assign the compressed string and
to a variable. (None of the various ways of compressing the string and
uses a banned letter; this is just the shortest option, after banning the uncompressed string.)
S Input string
⪪ Split on literal space
E Map over words
ι Current word
↧ Lowercased
⁼ Equals
η "and"
⎇ If true then
⟦ηιηιη⟧ Alternate lowercase and original word
⪫ Join with literal space
ι Otherwise the original word
⪫ Join everything with literal space
Implicitly print
Answered by Neil on December 10, 2021
Note: ɗ
is not a d
!
Ḳ,@ṁ5Kɗ€Œlẹ¥¦“2ɼ»Ṗ¤K
A monadic Link accepting a list of characters which yields a list of characters.
Note: and
is not in Jelly's dictionary, and its compression is “¡ÞṄɱ»
which we could use, but I decided to go with “2ɼ»Ṗ¤
which is also five bytes.
Ḳ,@ṁ5Kɗ€Œlẹ¥¦“2ɼ»Ṗ¤K - Main Link: list of characters, S
Ḳ - split (S) at spaces -> list of words
- (implicitly set the right argument to:)
¤ - nilad followed by link(s) as a nilad:
“2ɼ» - compression of "andy"
Ṗ - pop -> "and" -
¦ - sparse application...
¥ - ...indices: last links as a dyad - f(words, "and")
Œl - lower-case (all the words)
ẹ - indices of ("and" in the lower-cased words)
ɗ€ - ...action: last three links as a dyad for each - f(word,"and"):
@ - with swapped arguments:
, - pair -> ["and", word]
ṁ5 - mould like five -> ["and", word, "and", word, "and"]
K - join with spaces
K - join with spaces
Answered by Jonathan Allan on December 10, 2021
Saved 17 bytes thanks to Dom Hastings
<?php $b=chr(97);$c=XWT^"990";echo(preg_repl.$b.ce)("/b$cb/i","$c \0 $c \0 $c",${$b.rgv}[1]);
<?php $b=chr(97);$c=$b.chr(110).chr(100);$e=preg_repl.$b.ce;echo$e("/b($c)b/i","$c \1 $c \1 $c",${$b.rgv}[1]);
<?php
$b = chr(97);
$c = $b . chr(110) . chr(100);
$e = "preg_repl{$b}ce";
echo $e("/b($c)b/i", "$c \1 $c \1 $c", ${$b . "rgv"}[1]);
chr(97)
resolves to 'a', chr(110)
to 'n', and chr(100)
to 'd'.
PHP allows you to define a variable as a string, then execute a function with the standard function syntax. e.g.:
$d = 'print';
$d('hello world'); // Parsed as print('hello world');
Using this I am able to execute the preg_replace function by interpolating the chr(97)
from earlier and run a case insensitive regex to perform the necessary operation.
The final issue comes from input variables in PHP being e.g. $argv[1]
- and they're always argv. Fortunately PHP has a variable variable syntax, so ${'argv'}
is the same as $argv
- so I simply concatontate my chr(97)
to 'rgv' and execute in variable variable syntax.
Finally, a few bytes are saved by using PHP's assumptions. An unquoted string is how to reference a constant in PHP. Undefined constants are assumed to be their own name.
Answered by Scoots on December 10, 2021
-(3+1) from Kevin Cruijssen, -1 from ovs, -1 from Neil's Charcoal answer.
#εÐl'€ƒQils‚5∍]˜ðý
# Space split
ε Map:
Ð Triplicate
l lowercase
'€ƒQ == "and"?
i If true:
l Lowercase
s‚ Paired with original
5∍] Extend to 5 items
(Else: return the current item)
˜ Flatten
ðý Join by spaces
Answered by user92069 on December 10, 2021
Saved 1 byte thanks to @tsh
s=>s.replu0061ce(/bx61x6ex64b/gi,(x=(y='x61x6ex64')+' $& ')+x+y)
Without escaped characters, this simply reads as:
s=>s.replace(/bandb/gi,(x=(y='and')+' $& ')+x+y)
Answered by Arnauld on December 10, 2021
-p -040 -l
, 35 bytesThis script contains unprintables so the link is to a Bash program that builds the script and runs the tests.
$s= ~'...';s/^$s$/$s $& $s $& $s/gi
Uses Perl s///
ubstitution operator, but necessitates that and
is built outside due to the source restriction. To create and
, the $s
is set to ~"x9ex91x9b"
using the raw bytes (hence using xxd
). I started with "x61x6ex64"
and tried to look for shorter approaches. I also looked at PWQ^"195"
and variants of that, and v97.110.100
, but ~
was shortest. Once that string is created, it's possible to s///
ubstitute it surrounded by start and end anchors (^
and $
) due to the -040
command-line switch which uses space (ASCII 32, octal 040) as the record separator (which is also stripped off by -l
) making $_
equal just the words themselves, with case-/i
nsensitivity, with the string ($s
) and the matched string $&
as required, /g
lobally within the input.
-p040l
, 41 bytesWithout using RegEx. Link shows 50 bytes because I'm using the xXX
notation. Will fix when I'm not on mobile!
$s= ~"x9ex91x9b";$_=lc eq$s?"$s $_ $s $_ $s":$_
Answered by Dom Hastings on December 10, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP