13
\$\begingroup\$

The challenge is simple: write a program which takes in some non-empty string \$n\$ consisting of only uppercase and lowercase ASCII letters, and outputs the code for a program (in the same language) which takes in no input and outputs \$n\$. However, the code your program generates must not contain \$n\$ as a substring. For example, if your program was in Python, if the input was "rin", your output could not be print("rin"), because that contains the string rin (twice). One valid output would be, for example, x=lambda:'r\151n'.

Some notes:

  • Uppercase and lowercase characters are treated as distinct -- e.g. if the input string contains A, your generated code can still contain the character a.
  • Your generated code follows the same restrictions as a standard code golf answer -- e.g. it can be code which defines an anonymous function returning the string, but it cannot work by saving the string into a variable.
  • Your submission is scored by the length of the generating code, not the generated code. In addition, there are no restrictions on the source of the generating program, only the generated.

Standard loopholes are forbidden. As this is , shortest program wins.

\$\endgroup\$
9
  • 6
    \$\begingroup\$ @corvus_192 This other challenge is much more restrictive: without using any characters from that string in the code vs must not contain n as a substring. \$\endgroup\$
    – Arnauld
    Nov 8, 2023 at 18:42
  • \$\begingroup\$ is é a letter? \$\endgroup\$
    – MarcMush
    Nov 8, 2023 at 22:06
  • 1
    \$\begingroup\$ @MarcMush The input is restricted to [A-Za-z]*. \$\endgroup\$ Nov 8, 2023 at 23:57
  • \$\begingroup\$ I initially thought that the challenge was different, but I see that people are just "recycling" answers from the other challenge (someone giving credit to the original author). \$\endgroup\$
    – G B
    Nov 9, 2023 at 6:51
  • 2
    \$\begingroup\$ I think that "must not contain 𝑛 as a substring" hints that input cannot be empty, because the empty string is a substring of every possible string, including empty string. \$\endgroup\$ Nov 9, 2023 at 18:51

17 Answers 17

6
\$\begingroup\$

Python, 54 45 bytes

lambda x:f'eⅺt("\%o{x[1:]}")'%ord(x[0])

Attempt This Online!

Python lambda that returns a string that has a full Python program to print the string (on stderr). Used full-width characters (which are non-ASCII and so won’t appear in the input). Inspired by @UnrelatedString’s answer to a different question.

Thanks to @ShadowRanger for saving two bytes, @JonathanAllan for saving a further four and @dingledooper for three more again!

R, 66 bytes

\(x,s=substring)sprintf('\\()"\\%o%s"',utf8ToInt(s(x,1,1)),s(x,2))

Attempt This Online!

Equivalent program in R (but returns an anonymous function)

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Shave two characters by using an f-string to inline the part that's not benefiting from printf-style formatting. Once there's only one item being printf-formatted, you don't need the parens anymore: lambda x:f'print("\\%o{x[1:]}")'%ord(x[0]) \$\endgroup\$ Nov 9, 2023 at 0:05
  • 1
    \$\begingroup\$ You can save a few bytes by using the character in place of the xi \$\endgroup\$ Nov 9, 2023 at 19:56
6
\$\begingroup\$

Google Sheets, 37 50 47 41 bytes

="=символ("&code(A1)&")&"""&mid(A1,2,9^9)

Put the input in cell A1 and the formula in B1.

The formula assumes that the input string \$n\$ consists of uppercase and lowercase Latin letters only.

When the input is rin, the formula outputs =символ(114)&"in which is a valid formula in Google Sheets in any locale, including Latin locales such as United States. When the output is evaluated as formula, its result is rin.

Given a single letter such as A, the formula outputs =символ(65)&" which gives the result A.

The formula defends against substrings being part of the output code by not including any Latin letters in the output except those found in input. The first letter is "escaped" by using the equivalent of the char() function in Cyrillic, символ(), whose name doesn't match any Latin letters (console.log('символ'.match(/\w/))null).

\$\endgroup\$
0
4
\$\begingroup\$

Ruby, 38 31 29 bytes

->n{"$>.<<''<<"+n.bytes*'<<'}

Attempt This Online! Generates string in such a way that it never contains any letters.

-7 bytes from Value Ink and another -2 from ShadowRanger.

\$\endgroup\$
3
  • \$\begingroup\$ n.bytes is shorter than n.unpack for this character set \$\endgroup\$
    – Value Ink
    Nov 8, 2023 at 19:41
  • \$\begingroup\$ @ValueInk Good catch, thanks. \$\endgroup\$
    – Kirill L.
    Nov 8, 2023 at 19:43
  • \$\begingroup\$ @KirillL.: You can make the $><< bind tightly enough that the appends all occur before the output to $> with two fewer characters by explicitly making it an operator method call, removing the need for $== for precedence purposes, getting it down to 29 bytes: ->n{"$>.<<''<<"+n.bytes*'<<'} \$\endgroup\$ Nov 8, 2023 at 23:53
3
\$\begingroup\$

brainfuck, 95 63 bytes

-32 bytes thanks to @emanresu A

--[>+<++++++]>[->+>+<<]>+++>>----[>+<----]>-<,[[-<.>]<<.>>>.<,]

Try it online!

Essentially an ultra basic constant string generator. For each character code, outputs +.[-] where the + is repeated a number of times equal to the byte value of the input.

With Comments

--[>+<++++++]> Load a PLUS
[->+>+<<]   Copy it twice
>+++>       Change the other to a DOT
>----[>+<----]>- Load a RIGHT ANGLE BRACKET
<,[ Main loop WHILE NOT EOF
    [-<.>] Output a plus to increment the accumulator by one
    <<.>>>.< Output a DOT followed by a RIGHT ANGLE BRACKET
,] Repeat

\$\endgroup\$
3
  • 2
    \$\begingroup\$ Why not just append a > after each letter? \$\endgroup\$
    – emanresu A
    Nov 9, 2023 at 1:43
  • \$\begingroup\$ @emanresuA Because I didn't think of that \$\endgroup\$
    – ATaco
    Nov 9, 2023 at 2:30
  • \$\begingroup\$ (although at this point you could just steal the winning bfcat answer) \$\endgroup\$
    – emanresu A
    Nov 9, 2023 at 2:50
3
\$\begingroup\$

Zsh, 28 bytes

<<<'<<<${(#):-'$[#1]\}${1:1}

Try it online!

Similar idea to others, convert the first character to its character code, then ${(#):-NUM} converts it back when evaluated.

\$\endgroup\$
2
\$\begingroup\$

Julia 1.0, 40 bytes

!s="_->"*join("*('@'+$(i-'@'))" for i=s)

Try it online!

builds an anonymous function that concats (* in julia) chars together be adding to '@' eg 'A'==('@'+1) without using any letters

for example: ABC => _->*('@'+1)*('@'+2)*('@'+3)

\$\endgroup\$
3
  • \$\begingroup\$ Brilliant idea, both the @ usage and the concats. The question requires the output code doesn't take any input though, so the _ should be () instead. \$\endgroup\$
    – Sundar R
    Nov 26, 2023 at 3:49
  • \$\begingroup\$ I believe it is allowed \$\endgroup\$
    – MarcMush
    Nov 26, 2023 at 11:41
  • 1
    \$\begingroup\$ Pretty nice that that's codified as the default interpretation! \$\endgroup\$
    – Sundar R
    Nov 26, 2023 at 12:31
2
\$\begingroup\$

Jelly, 5 4 bytes

OṾ”Ọ

Try it online!

A full program that takes a string and prints a Jelly niladic link that outputs the string.

Thanks to @JonathanAllan for saving a byte!

Explanation

O    | Codepoints
 Ṿ   | Uneval (and implicitly print)
  ”Ọ | an "Ọ" (implicitly printed)
\$\endgroup\$
0
1
\$\begingroup\$

Uiua, 13 10 bytes

&p"-1"&s+1

Try it online!

(3 bytes saved by using &s)

Explanation

Simply encodes the string by incrementing all codepoints and decrementing in the output program

        +1 # increment all codepoints
      &s   # pretty-print (includes quotes)
&p"-1"     # print -1
\$\endgroup\$
0
1
\$\begingroup\$

Charcoal, 9 bytes

FS⁺´℅´I℅ι

Try it online! Link is to verbose version of code. Explanation: Prints a list of code points and commands to convert them back into characters. Sample generated program: Try it online!

\$\endgroup\$
1
\$\begingroup\$

J, 33 bytes

-:&'u'{'117{a."_',:~'u:@',3":@u:]

Try it online!

A function which outputs the source code of a function which outputs the original input. Since in J no-argument functions don't exist, we call the outputted function with a dummy argument 0 which is ignored.

Probably a better approach out there, but this idea is:

  • Return a function which uses "Unicode" u: to translate the code points of the original input back to unicode: u:@<literal list of code points>.
  • Everything is non-letter in that code except for u, so that's the one input we need to defend against. So for that specific case we return a function which returns the 117th letter of the J alphabet a., which is also u but whose code does not contain u: 117{a."_.

BQN, 19 bytes

""""∾˜"-⟜1∘"""∾+⟜1

BQN Online

Bonus my first BQN answer, using a similar code point shift approach as Pseudo Nym's Uiua answer.

Perhaps there is a better way to escape quotes?

\$\endgroup\$
2
  • \$\begingroup\$ ',@:>@;:@',quote@,@,.&' ' (25b) almost works except for single character strings if I understand the specifications correctly. I somewhat doubt this approach could leverage the saved 7/8b to account for this, though \$\endgroup\$ Nov 8, 2023 at 23:14
  • 1
    \$\begingroup\$ " single character strings" yes those are the rub. But TIL I learned about quote... thanks. \$\endgroup\$
    – Jonah
    Nov 8, 2023 at 23:20
1
\$\begingroup\$

JavaScript (V8), 57 52 bytes

-5 bytes thanks to @Arnauld

There was a shorter way

s=>`_=>"\\${s.charCodeAt().toString(8)+s.slice(1)}"`

The smallest representable Octal letter is A at 101, which means we don't actually need to pad this.

Try it online!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ 52 bytes \$\endgroup\$
    – Arnauld
    Nov 8, 2023 at 23:03
1
\$\begingroup\$

Retina, 39 bytes

T`Ll`lL
$
¶T`?-[_-{`_-{?-[
^t¶T
t¶Y
^
¶

Try it online! Explanation: Toggles the case of the input, then appends a command to toggle the case back. This command is normally T, but in the event that the input was T, uses the Y command instead, which has the same effect on a single character. Sample generated program: Try it online!

\$\endgroup\$
1
\$\begingroup\$

Python, 67 bytes

lambda s:[p:="print","lambda:"][s in p]+f"('\%o{s[1:]}')"%ord(s[0])

Attempt This Online!

Explanation

# if the input is a sub-string of print create a lambda function
#  otherwise create a print statement
[p:="print","lambda:"][s in p]
# replace first character to octal escape sequence
f"('\%o{s[1:]}')"%ord(s[0])

A string cannot be a sub-string of both print and lambda: so the input is not contained in the first half.
By replacing the first character with a number it is guaranteed that the string is not a sub-string of the second half (the string contains only letters).
Both parts are separated by ( which is guaranteed to not be in the input


Python, 87 bytes (ASCII only)

can handle empty string

lambda s:[l:="lambda:","print"][s in l]+"('%s')"%f"\%o{s[1:]}"%ord(s[0])if len(s)else""

Attempt This Online!

\$\endgroup\$
0
1
\$\begingroup\$

PowerShell, 30 107 bytes (PS 5/6), 91 bytes (PS 7)

The first attempt, as @nick-kennedy correctly pointed out, didn't account for single character strings.

PowerShell 5/6

%{If($_[1]){"'$(($_|% T*y)-join"'+'")'"}Else{"[$(If('char'|% Con* $_){'CHAR'}Else{'char'})]$(1*[char]$_)"}}

Input comes from the pipeline
Try it online!

PowerShell 7
PowerShell 7 (TIO is still on PS6) supports the ternary operator "?:", which allows to get rid of the two If/Else:

%{($_[1])?"'$(($_|% T*y)-join"'+'")'":"[$(('char'|% Con* $_)?'CHAR':'char')]$(1*[char]$_)"}
  • If the input is longer than 1 character: Breaks the input string into single characters and generates code to add them back together: 'r'+'i'+'n'
  • If the input is only one character: Casts the codepoint using either [char] or [CHAR], depending on the case of the character: [char]65 or [CHAR]97.

Output in PowerShell is implicit.
Ungolfed:

ForEach-Object {  # Takes input from the pipeline
    If ($_.Length -gt 1) {
        # $(...) is a subexpression which will be evaluated inside a string enclosed in double quotes
        # Turn the string to an array of characters, then join them back with the literal '+'
        "'$(($_ | ForEach-Object -MemberName ToCharArray) -join "'+'")'"
    } Else {  # single char
        # If the character is one of the critical chars (used to cast) is in lowercase, use uppercase for the [char] cast
        # 1*[char]$_: Multiplying an integer with a character will return the codepoint; shorter than [int][char]$_
        "[$(If ('char'.Contains($_)) {'CHAR'} Else {'char'})]$(1*[char]$_)"
    }
}

Test it in PowerShell 7 (can be pasted into a PS7 console):

$testcases = 'Hello World', 'char', 'a', 'A', 'b', 'B'
$codes = $testcases |
%{($_[1])?"'$(($_|% T*y)-join"'+'")'":"[$(('char'|% Con* $_)?'CHAR':'char')]$(1*[char]$_)"}
For ($i = 0; $i -lt @($testcases).Count; $i++) {
    "String input:   $(@($testcases)[$i])"
    "Generated code: $(@($codes)[$i])"
    "Executed code:  $(Invoke-Expression -Command @($codes)[$i])"
    '--'
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ @nick-kennedy Thanks, should be fixed now. \$\endgroup\$
    – user314159
    Nov 11, 2023 at 23:44
0
\$\begingroup\$

ARBLE, 28 bytes

'"\\%s"'%(byte(s)..sub(s,2))

Try it online!

\$\endgroup\$
0
\$\begingroup\$

JavaScript (V8), 96 bytes

-3 thanks to @Shaggy
-6 thanks to @tsh

I overlooked the rule allowing anonymous functions, so this generates a full program using either print or console.log with extra precaution for n which is present in both instructions.

s=>`${S="print",S.match(s)?'co\\u006esole.log':S}("\\${s.charCodeAt().toString(8)+s.slice(1)}")`

Try it online!

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 102 bytes \$\endgroup\$
    – Shaggy
    Nov 8, 2023 at 22:35
  • 1
    \$\begingroup\$ s=>`${S="print",S.match(s)?'co\\u006esole.log':S}("\\${s.charCodeAt().toString(8)+s.slice(1)}")` \$\endgroup\$
    – tsh
    Nov 10, 2023 at 2:58
0
\$\begingroup\$

05AB1E, 6 bytes

Ç„)ç)»

Output of the output program is a list of characters.

Try it online.
Try the outputted program.

Explanation:

Ç       # Convert the (implicit) input-string to a list of codepoint-integers
 „)ç    # Push string ")ç"
    )   # Wrap all values on the stack into a list
     »  # Join the inner list by spaces and then the strings by newline
        # (after which the result is output implicitly with trailing newline)

Minor note: the second ) cannot be the more straight-forward (pair) nor ª (append to list), because „)ç‚ and „)çª would be interpret as dictionary words ") reservoir" and ") baghdad" respectively.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.