53
\$\begingroup\$

Challenge

Given a non-empty string S of length L consisting entirely of printable ASCII chars, output another string of length L that consists entirely of printable ASCII chars, but is not equal to S.

For the purposes of this challenge, a printable ASCII char is one between U+0020 and U+007E, inclusive; that is, from (space) to ~ (tilde). Newlines and tabs are not included.

For example, given "abcde", some valid outputs could be:

  • "11111"
  • "abcdf"
  • "edcba"

But these would be invalid:

  • "abcde"
  • "bcde"
  • "abcde0"

Test cases

"asdf"
"1111"
"       "
"~~~~~"
"abcba"
"1"
" "
"~"
" ~"
"~ "
"  0"
"!@#$%^&*()ABCDEFGhijklmnop1234567890"
" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"

Rules

  • You may assume the input consists entirely of printable ASCII chars.
  • You may not assume that the input does not contain all 95 printable chars.
  • You may assume the input contains at least one character and is less than 256 chars long.
  • The output must also consist entirely of printable ASCII chars. You could not, for example, output the byte \x7F for input "~".
  • The output must be different than the input with probability 1; that is, you may generate random strings until one is different than the input, but you can't just output L random characters and hope it's different.
  • Newlines are disallowed in the output, but you may output one trailing newline which is not counted toward the string.

Scoring

This is , so the shortest code in bytes in each language wins.

\$\endgroup\$
  • \$\begingroup\$ Note that "positive" excludes the empty string. For extra clarity, maybe replace "positive" with "nonzero"? \$\endgroup\$ – CalculatorFeline May 30 '17 at 20:30
  • 5
    \$\begingroup\$ @CalculatorFeline But that would include negative-length strings /s \$\endgroup\$ – ETHproductions May 30 '17 at 20:36
  • 1
    \$\begingroup\$ ...Those don't exist. \$\endgroup\$ – CalculatorFeline May 30 '17 at 20:38
  • \$\begingroup\$ @CalculatorFeline Better now? \$\endgroup\$ – ETHproductions May 30 '17 at 20:40
  • 3
    \$\begingroup\$ Another simple but not trivial challenge. \$\endgroup\$ – Weijun Zhou Apr 4 '18 at 15:03

69 Answers 69

2
\$\begingroup\$

PowerShell, 37 26 bytes

Thanks Mazzy for -11 bytes

-join($args|% t*y|%{$_%9})

Try it online!

Does alright. Uses the ToCharArray trick to save some bytes. Through a conversion chain, mods the ASCII value of each character by 9 then joins up the value.

\$\endgroup\$
  • \$\begingroup\$ ? 6+3*($_-eq6) \$\endgroup\$ – mazzy Dec 28 '18 at 5:52
  • 1
    \$\begingroup\$ ? $_%9 :))))) \$\endgroup\$ – mazzy Dec 28 '18 at 7:52
0
\$\begingroup\$

Tcl, 56 bytes

proc C s {join [lmap x [split $s ""] {expr {$x==0}}] ""}

Try it online!

Approach very similar to last one: replaces every non-zero by a zero and every zero by one.


Tcl, 62 bytes

proc C s {puts [expr {[string in $s 0]==0}][string ra $s 1 e]}

Try it online!

Approach replaces first character by 1 if it is a 0, else it replaces anything else by a 0.

Tcl, 83 bytes

proc C s {scan [string in $s 0] %c f
puts "[format %c [incr f]][string ra $s 1 e]"}

Try it online!

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

SmileBASIC, 27 25 bytes

DEF D S
S[0]=@1[S>"2"]END

Creates a function named D that is called like:

STRING$="abcde"
D STRING$
'STRING$ is now "1bcde"

The first character is replaced with either @ or 1

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

C (gcc), 22 bytes

f(char*s){*s=~1&*s^2;}

Try it online!

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

Jstx, 2 bytes

☺å

Try it online!

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

Python 3, 29 26 bytes

lambda s:'a~'[s<'~']+s[1:]

Try it online!

  • Replacing first character with ~, if the first character is ~ already, it is replaced by a.
\$\endgroup\$
1
\$\begingroup\$

><>, 9 3 bytes

5%n

Try it online!

Takes input through the -s flag. Mods each digit with 5 and prints the integer, ending when the stack is empty. This results in only 5 possible output characters, 0-4. Each of those numbers when inputted will produce themselves plus 3, as the ASCII value of 0 is 48, which mod 5 is 3. While the output is reversed, no number is equivalent to another.

Both 7, 9 and a(10) also work as they are not factors of 48 and print single digits.

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

R, 40 bytes

function(s)substr(shQuote(s),1,nchar(s))

This uses the shell quoting function shQuote to place appropriate quotes around a string and escape quotes within the string (similar to @xnor's answer). Then take a substring that's as long as the original string (because the string might have multiple escaped characters, we need to take a substring of the correct length, so we can't just use substring(...,3)). sQuote is shorter, but converts to ‘‘’.

Another approach, using more 'core' R stuff is 46 bytes:

function(s)sub(".",letters[grepl("^a",s)+1],s)

Substitute the first character with 'a', unless it is 'a', then substitute it for 'b'. sub only substitutes the first match, so we don't need ^. letters is constant and a slightly shorter way of doing c("a","b"). grepl returns a boolean, and adding 1 converts it to a number that indexes letters. The ^ is needed to correctly convert "ba".

Code to test

x = function(s)substr(shQuote(s),1,nchar(s))

test = function(t){
  t2 = x(t)
  t2!=t & nchar(t)==nchar(t2)
}

testStrings = c("a","b","ab","ba","aa",
                "'","'\"","\\\\",'"','""',
                '‘','’',"~","asdf",
                "1111","       ","~~~~~","abcba",
                "1"," ","~"," ~","~ ","  0",
                "!@#$%^&*()ABCDEFGhijklmnop1234567890",
                " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~")

all(sapply(testStrings,test))
\$\endgroup\$
  • \$\begingroup\$ Welcome to PPCG! This answer is not, at the moment, valid, because it assumes input is given as a hard-coded variable s. You can either submit this as an anonymous function, function(s)substr(shQuote(s),1,nchar(s)), or take input via scan(,""), readLines() or similar. I've upvoted this to give you enough rep to post in the R golfing chatroom; feel free to ping me there if you have any questions! This is a very well-explained answer :) \$\endgroup\$ – Giuseppe Apr 6 '18 at 17:26
  • \$\begingroup\$ @Giuseppe A ha, thanks! I've edited the answer. \$\endgroup\$ – Sean Roberts Apr 8 '18 at 10:40
0
\$\begingroup\$

Gol><>, 6 bytes

iE;5%n

Try it online!

Direct translation of Jo King's ><> answer.

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

str, 2 bytes

XV

Try it online!

Explanation

XV
       over each character:
X         increment it  ("~" becomes "\x7f" and "@" becomes "A")
 V        wrap to printable ascii ("\x7f" becomes " ")

Alternatively, YV to decrement instead of increment.

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

Pyth, 9 bytes

*h-+QGhQl

Try it here

Explanation

*h-+QGhQl
   +QG      Stick the alphabet to the end of the input.
  -   hQ    Delete all instances of the first character.
 h          Take the first remaining character.
*       lQ  Multiply by the length of the (implicit) input.
\$\endgroup\$
2
\$\begingroup\$

Perl 6, 14 bytes

{.ord%7~.chop}

Try it online!

Bare block, implicit lambda with input $_. The ordinal of the first character .ord modulo 7 is a different character: Non-numeric first character becomes numeric, numeric first characters map to a different character. If we append the input sans the last character (~ $_.chop), we match the length. It can never match the input because the first character never matches.

Perl 6, 15 bytes

{S/./{.ord%7}/}

Performs S/// substitution (which returns the result of substituting on $_), matching . (any character) once, and replacing it with the ordinal of the first character in $_ - the same character - modulo 7. Non-numeric first character becomes numeric, numeric first characters map to a different character.

Try it online!

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

Brain-Flak, 42 bytes

({}[((((()()()()){}){}){})]<>){{}}([]<>{})

Try it online!

Replaces the first character of the string with a space, or a ! if the first character is already a space.

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

Swift 3, 76 68 bytes

let s=readLine()!;print(s.characters.map{$0=="a" ?"b":"a"}.joined())

Try it online!

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

Pyth, 12 bytes

+C+%ChQlG32t

Test suite

Python 3 translation:
Q=eval(input())
print(chr(ord(Q[0])%26+32)+Q[1:])
\$\endgroup\$
0
\$\begingroup\$

SNOBOL4 (CSNOBOL4), 71 bytes

	INPUT LEN(1) . X REM . S
	X =IDENT(X) 1	:S(O)
	X =0
O	OUTPUT =X S
END	

Try it online!

Replaces the first character of S with a 0 unless it's already, 0 in which case it swaps it with 1.

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

Fortran (GFortran), 77 bytes

CHARACTER(256)A
READ*,A
A(1:1)=CHAR(MOD(IACHAR(A(1:1))+1,94)+33)
PRINT*,A
END

Try it online!

It does what was required... well, with some issues...

1) If the first character is "or <space>, they will be ignored;

2) If there is /, it will be understood as something like "end of transmission";

3) There will be a leading space (which is not part of the output (so do I think), because Fortran always prints a leading space if the output is not formated) and up to 255 trailing spaces. This last problem (i.e., the trailing spaces) can be solved using no more then six bytes.

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

Java 8, 39 38 bytes

s->(s.charAt(0)<49?9:0)+s.substring(1)

Try it online.

Explanation:

If the first character has a unicode value below 49 (space, or one of !"#$%&'()*+'-./0), change it to a '9', else change it to a '0'.

s->                 // Method with String as both parameter and return-type
  (s.charAt(0)<49?  //  If the first character has a unicode value below 49:
    9               //   Change the first character to a '9'
  :                 //  Else
   0)               //   Change the first character to a '0'
  +s.substring(1)   //  And return the rest of the input-String (if any)
\$\endgroup\$
0
\$\begingroup\$

Julia 0.6, 26 bytes

s->map(x->x<'b'?'b':'a',s)

Try it online!

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

Perl 5, 23 + 1 (-p) = 24 bytes

s/./chr 65+ord($&)%26/e

Try it online!

Blatantly steals @FlipTack's method to change the first character to a different upper case letter.

\$\endgroup\$
  • \$\begingroup\$ You can drop one of the digits in 26, at least. \$\endgroup\$ – Ørjan Johansen Jan 11 '18 at 0:51
3
\$\begingroup\$

Pushy, 1 byte

Q

Try it online!

This converts the given string into list of ASCII character codes, indexes them (modular indexing) into the uppercase alphabet, then prints the result. Essentially, each character n is mapped to chr(ord(n) % 26 + 65). You can use this program to see how the mapping works.

The output:

  • Will always be the same length as the input, as the characters are directly mapped into new ones.
  • Will always comprise only printable ASCII characters (as it only contains uppercase letters)
  • Will always be different to the input, as there is no possible input character n such that chr(ord(n) % 26 + 65) == n, as for this to be true there must be an integer x such that 26x = 65, for which there is no solution.

1 byte

q

Try it online!

This answer is exactly the same, except that it maps to lowercase alphabet characters rather than uppercase alphabet characters. This is still valid as there is no possible input character n such that chr(ord(n) % 26 + 97) == n.

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

x86 opcode, 6 bytes

    and     byte [ecx], 0xF1
    inc     byte [ecx]
    ret     
\$\endgroup\$
2
\$\begingroup\$

brainfuck, 35 27 bytes

Edit: switched to a better way of generating an odd number thanks to the brainfuck constants page

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

Try It Online

Prints out a string of semi-random Vs and Us. If the first character of the input is a V it will print out a U instead and vice versa.

How it Works

,[ Gets first inputted char 
  [[>]+<[-<]>] Converts the ASCII value to binary
  -[>+<---] Adds 85 to the last digit of that binary, which is the original value mod 2. 
            This converts a V (value 86) into a U (value 85) and vice versa
  >. Print the value
,] Get a new value and repeat. 
   Note that the binary of the previous value is still in memory, 
     so it no longer prints specific chars for odd or even values

Another version with the same bytecount:

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

Only changes the first character to a V or a U, but doesn’t handle empty input (which is still valid)

\$\endgroup\$
  • 1
    \$\begingroup\$ Great algorithm--it's tricky to find short algorithms to do things in BF. Don't think the second one works though; shouldn't the last bit be [.,]? \$\endgroup\$ – ETHproductions Dec 26 '17 at 19:50
0
\$\begingroup\$

BrainFuck, 49 47 Bytes

,>++++[-<-------->]++[<]++++[->++++++++<]>-[.,]
x           0   (x-32) 2                (x-32||2)+31
^           ^(x>32) ^(x==32)

Assuming EOF as zero

\$\endgroup\$
  • \$\begingroup\$ You can cut out the first set of ., and just go straight into the loop \$\endgroup\$ – Jo King Dec 26 '17 at 15:54
  • \$\begingroup\$ Thanks \$\endgroup\$ – l4m2 Dec 27 '17 at 0:26
2
\$\begingroup\$

C/C++, 29 bytes

void m(char*s){(*s%=26)+=65;}

Code to test :

#include <iostream>
#include <string>
#include <cassert>

#ifdef _MSC_VER
#pragma warning(disable:4996)
#endif

void m(char*s){(*s%=26)+=65;}

int main() {
    std::initializer_list<std::string> test{
        "asdf",
        "1111",
        "       ",
        "~~~~~",
        "abcba",
        "1",
        " ",
        "~",
        " ~",
        "~ ",
        "  0",
        "!@#$%^&*()ABCDEFGhijklmnop1234567890",
        " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
    };

    for (auto&a : test) {
        char* t = new char[a.size() + 1];
        std::strcpy(t, a.c_str());
        m(t);
        assert(a != t);
        std::cout << a << " => " << t << '\n';
        delete[] t;
    }
}
\$\endgroup\$
0
\$\begingroup\$

Charcoal, 8 bytes

FSIX⁰⁼ι1

Try it online! Link is to verbose version of code. Works by comparing each character to 1, then taking the result as the exponent of zero, then converting to string. This results in an output 0 for each 1 in the input and a 1 for each other character. Edit: Changes in Charcoal now mean that I can directly cast the result of Equals saving 2 bytes: FSI⁼ι0 Try it online! Link is to verbose version of code. Edit: Actually there was a 6-byte solution all along: FS§α℅ι Try it online! Link is to verbose version of code. Port of @FlipTack's Pushy answer. (Also works with lower case of course.)

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

Funky, 26 22 bytes

s=>s::gsub("."a=>1&~a)

Calculates ~a which for non-digits will return NaN. Then 1& limits it to either 0 or 1, for the digit 0, this will be 1, and for 1 this will be 0. So this string is always unique.

Try it online!

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

Implicit, 15 14 bytes

'_._` !{+32}*-

Found about 10 interpreter bugs writing this. Try it online!

'_._` !{+32}*-
'                « read string                              »;
 _               « push last char onto stack                »;
  .              « increment                                »;
   _`            « mod by 127 (the "` " evaluates to 127)   »;
      !{...}     « if falsy (char was ~)                    »;
        +32      «  add 32 (make it a space)                »;
            *    « stick char at beginning of string        »;
             -   « pop last char off string                 »;
\$\endgroup\$
2
\$\begingroup\$

Golfscript, 3 bytes

Try it online!

)5%

Take the last character's ASCII value modulo 5, and replace the last character with the result. This obviously works for non-digit characters, but if the last character is a digit, it also changes ("0" mod 5 = 3, "1" mod 5 = 4, etc).

This would also work with 7 or 9 while still keeping the same length.

Also, yay! I have a Golfscript solution as good as the best solutions here!

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

Perl 5, 49 bytes

sub{$_="a"x length $_[0];$_++while $_ eq$_[0];$_}

Explanation:

  • starts with string of letter "a" as long as input
  • keeps incrementing that until it's different from input

Starting from "a"s was to avoid incrementing to point where Perl lengthens the string; with only one strings to avoid being same as, it couldn't overflow.

This is shamelessly cribbed (and simplified) from my answer to the "related" problem "The Third String".

Execute with:

perl -e '$s = ' -E 'sub{$_="a"x length $_[0];$_++while $_ eq$_[0];$_}' -E ';say $s->("z")'
\$\endgroup\$
  • \$\begingroup\$ How can it need to increment more than once? \$\endgroup\$ – Phil H Apr 4 '18 at 15:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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