TransWikia.com

And and… and. And.?

Code Golf Asked by Kevin Cruijssen on December 10, 2021

Introduction:

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

With my answer:

Challenge:

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

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.

Challenge rules:

  • Your source code cannot contain any of the characters aAnNdD.
  • You can assume the input-string only contains spaces and letters (both lower- and uppercase)
  • You can assume the input is non-empty
  • It is possible that the input-string does not contain the word ‘and’, in which case it’s returned as is
  • Instead of a string you are also allowed to take the input as a list/array/stream of characters/code-point-integer (or other similar variations)
  • Don’t replace substrings of and if it isn’t a standalone word (see test cases with stand, band, and Anderson)

General rules:

  • This is , so shortest answer in bytes wins.
    Don’t let code-golf languages discourage you from posting answers with non-codegolfing languages. Try to come up with an as short as possible answer for ‘any’ programming language.
  • Standard rules apply for your answer with default I/O rules, so you are allowed to use STDIN/STDOUT, functions/method with the proper parameters and return-type, full programs. Your call.
  • Default Loopholes are forbidden.
  • If possible, please add a link with a test for your code (i.e. TIO).
  • Also, adding an explanation for your answer is highly recommended.

Test cases:

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"

20 Answers

Lua, 151 bytes

b="97110100"_G["lo97100"]('pri110t(97rg[1]:gsub("%w+",fu110ctio110(s)retur110 s:lower()==b '..b..' (b.." "..s.." "):rep(2)..b e110100))')()

Try it online!

How It Works

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.

Readable Version

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

Wolfram Language (Mathematica), 116 112 bytes

-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

GNU sed, 38 bytes

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.

Try it online!

Answered by RobertR on December 10, 2021

Stax, 32 26 bytes

å╔é╩⌐╬²ßxæ╬:Ö5ò▌@ Θ5YS₧Ñπε

Run and debug it

I knew packed stax mutation was good for something.

Saved 6 bytes thanks to an anonymous donor.

Answered by Joshua on December 10, 2021

Dyalog APL, 99 95 93 92 39 bytes

(7⍴'b',⎕ucs 65 78 68)⎕R(15⍴'l& & ')⍠1

Try it online!

Golfed ... a lot of bytes thanks to @Adám

Answered by Ada on December 10, 2021

Python 3.8, 102 bytes

k=iⁿput().split();o=[]
while k:w,*k=k;o+=([w],[x:=w.lower(),w,x,w,x])["x61x6ex64"==x]
priⁿt(*o)

Try it online!


Python 3.8, 106 104 bytes

-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()],[]))')

Try it online!

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

C (gcc), 179 176 157 152 149 bytes

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

Try it online!

Assumptions

  • ASCII
  • Little-endian
  • 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.

Breakdown

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

Pip -s, 34 bytes

Y Jz@[i13 3]{(gPEyLC@gQy?,5o)}Mq^s

Try it online!

Explanation

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

Pip, 34-bytes (no flags)

Y Jz@[i13 3]qR-:yWR`b`yWR` & `WRy

Try it online!

Explanation

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

Python 3, 160 151 149 bytes

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]")

Try it online!

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.

Explanation

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

Haskell, 177 bytes

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

Try it online!

Explanation

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.

More boring version, 174 bytes

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

Try it online!

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

sed, 70 $cdots$ 56 52 bytes

Saved 4 bytes thanks to Dom Hastings!!!

s/bx61x6ex64b/&  &  &/Ig;s/&/x61x6ex64/g

Try it online!

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

Excel, 437 435

Closing quotes and parens already discounted. It's not pretty, but I found some surprising optimizations.

Setup

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.

How It Works

  • B2 - 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.
  • The rest of the Cells in Column B simply enumerate all possible capitalizations of "and".
  • C2 - We first surround the input with spaces so edge handling is easier. Then replace "and" with 5 of itself.
  • After this, the rest of the cells in column C replace occurrences of the corresponding capitalization permutation in column B with the sandwiched string.
  • In the last cell, trim off the surrounding spaces.

Note

  • Nesting the C's gives us no advantage because we trade off the equals sign for the auto-closed parens.

Answered by Calculuswhiz on December 10, 2021

Japt, 22 21 bytes

Work in progress

r`%ß@%b`È3ÇXvÃqXû5}'i

Try it

Original (w/ -S flag)

¸cÈv ¶`ß@`Å?5ogX¸iXv:X

Try it

¸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

Scala 2.12, 126 116 bytes

"(?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.

Try it online

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

Charcoal, 29 bytes

≔“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

Jelly,  23 22 21  20 bytes

Note: ɗ is not a d!

Ḳ,@ṁ5Kɗ€Œlẹ¥¦“2ɼ»Ṗ¤K

A monadic Link accepting a list of characters which yields a list of characters.

Try it online!

How?

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

PHP, 97 bytes

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

Try it online!


PHP, 114 bytes

<?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]);

Try it online!

Ungolfed

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

05AB1E, 18 bytes

-(3+1) from Kevin Cruijssen, -1 from ovs, -1 from Neil's Charcoal answer.

#εÐl'€ƒQils‚5∍]˜ðý

Try it online!

Explanation

#                   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

JavaScript (ES6),  76 74  73 bytes

Saved 1 byte thanks to @tsh

s=>s.replu0061ce(/bx61x6ex64b/gi,(x=(y='x61x6ex64')+' $& ')+x+y)

Try it online!

Without escaped characters, this simply reads as:

s=>s.replace(/bandb/gi,(x=(y='and')+' $& ')+x+y)

Answered by Arnauld on December 10, 2021

Perl 5 + -p -040 -l, 35 bytes

This 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

Try it online!

Explanation

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-/insensitivity, with the string ($s) and the matched string $& as required, /globally within the input.


Perl 5 + -p040l, 41 bytes

Without 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":$_

Try it online!

Answered by Dom Hastings on December 10, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP