# Negative of an ASCII photo

Given an $$\m\times n\$$ binary ascii "photo", return the negative of the photo

Example:

  #
# #
#   #
# #
#
->
## ##
# # #
###
# # #
## ##


# General rules:

• This is , so the shortest answer in bytes wins
• Standard rules and default I/O rules apply
• Your output characters must be the same as your input characters (e.g. ["#"," "] -> [" ","#"]), which you are free to choose (but must be printable characters)
• Your output photo must have the same $$\m\times n\$$ dimensions as the input
• Trailing whitespace is allowed

# Test cases

Input 1:

  #
# #
#   #
# #
#


Output 1:

## ##
# # #
###
# # #
## ##


Input 2:

    # #
#####
# #
#####
# #


Output 2:

#### #
##
## # ##
##
# ####


Input 3:

##############################################################################################
#  ###  ##       ##  #######  #######       ######  ###  ##       ##       ##  #######      ##
#  ###  ##  #######  #######  #######  ###  ######  ###  ##  ###  ##  ###  ##  #######  ###  #
#       ##     ####  #######  #######  ###  ######  # #  ##  ###  ##       ##  #######  ###  #
#  ###  ##  #######  #######  #######  ###  ######   #   ##  ###  ##  #  ####  #######  ###  #
#  ###  ##       ##       ##       ##       ######  ###  ##       ##  ###  ##       ##      ##
##############################################################################################


Output 3:

 ##   ##  #######  ##       ##       #######      ##   ##  #######  #######  ##       ######
##   ##  ##       ##       ##       ##   ##      ##   ##  ##   ##  ##   ##  ##       ##   ##
#######  #####    ##       ##       ##   ##      ## # ##  ##   ##  #######  ##       ##   ##
##   ##  ##       ##       ##       ##   ##      ### ###  ##   ##  ## ##    ##       ##   ##
##   ##  #######  #######  #######  #######      ##   ##  #######  ##   ##  #######  ######

• Duplicate, not sure which one Mar 15 at 20:57
• @Fmbalbuena if you can't find the duplicate then surely it isn't a duplicate? Mar 15 at 21:06
• No, but I need help of someone to find the duplicate Mar 15 at 21:11
• @Fmbalbuena yeah I did have a look, but couldn't find anything Mar 15 at 21:13
• I think rules are kind of blurry as any input is allowed and any input characters is valid? so that makes a 01 matrix valid input? leaving it to |m-1|? Mar 18 at 12:12

# Python 3, 31 bytes

lambda s:s.translate(9*"# \n ")


Try it online!

### How

The 9*"# \n " is a string that has a "\n" at position 10 which matches its own code point, and at positions 32 and 35 it has copies of "#" and " " so these two are at each other's code point. str.translate uses this string as a lookup table replacing each character of s by the value associated with its code point. It will leave newlines in place and swap hashes and spaces.

• oh wow this is clever!! I dont think I would have ever thought to multiply the string like that Mar 15 at 22:54
• I'd love an explanation of how this works Mar 16 at 0:32
• @jezza the s.translate(t) function scans the characters of s and replaces each character c with the character that resides in the string t in the position asc(c), with asc the ASCII code number of the character c. What this solution does is efficiently construct a string t with \n at position 10 (which is the ASCII code of \n), a space at position 35 (which is the ASCII code of #) and a # at position 32 (which is the ASCII code of space). Mar 16 at 9:00
• The string t is constructed as 9 consecutive concatenated copies of the 4-character string “# \n “ (hash, space, newline, space). For example, there’s a \n in position 2, and after concatenation also in positions 6 and 10, and 10 is what we want. Similarly there’s a # in position 0, 4, 8 and so on through 32, and “ “ in position 3, 7, 11, …, 35. Mar 16 at 9:03
• I daresay this could save a byte by using the rule that you can define your own input/output characters (except the newline)
– Dave
Mar 17 at 22:00

# sed, 23 8 bytes

-15 bytes thanks to Digital Trauma

y/# / #/


Try it online!

• Try y/# / #/ :) Mar 15 at 21:27

# C (tcc), 33 bytes

Function that modifies its input.

f(char*s){*s^=1^*s%3;*++s&&f(s);}


Try it online!

# JavaScript (V8), 25 bytes

s=>s.replace(/./g,i=>i^1)


Try it online!

Takes input as string of 0's, 1's, and newlines.

Explanation:

s => s.replace(
/./g,       // '.' matches anything but newline, ie. 0 or 1 only.
// 'g' marks regex as global, to replace everything
i => i ^ 1  // JavaScript's aggressive type casting forces '0' or '1' string into a number
// boolean XOR (^) with 1 transforms 0 -> 1 and 1 -> 0
)

• 1-i would also work, I assume.
– Neil
Mar 20 at 18:44
• @Neil, Yes that also works. Probably a bit simpler, but no byte difference so I'll keep it as is. Mar 20 at 21:33

# Bash + coreutils, 12

tr '# ' ' #'


Try it online!

• Apparently you can escape the leading space instead of quoting the second string: tr '# ' \ #
– ovs
Mar 15 at 22:07
• If you used an alternative character that wasn't magic (# is the comment character) then you could do that with the first space too.
– Neil
Mar 15 at 22:33
• @ovs You can also do tr #\ \ #
– iBug
Mar 16 at 16:42
• @iBug As Neil mentioned # starts a comment, so this only works if you use a different character than #.
– ovs
Mar 16 at 16:49
• if you define your characters as t and r you can use tr rt tr!
– Dave
Mar 17 at 22:04

# Lua, 68 bytes

a=io.read('*a')b,d=a.gsub,' 'print((b(b(b(a,'#','!'),d,'#'),'!',d)))


Attempt This Online!

# Pip, 3 bytes

1-_


Maybe this is too cheaty?

The solution is a function that takes and returns a list of lists of 0s and 1s. Attempt This Online!

Explanation: subtract each number from 1.

Here's a 6-byte version that's on much safer ground rules-wise. It's also a function, and it also uses 0 and 1, but it takes and returns a multiline string:

_TRt01


Attempt This Online!

Explanation: Transliterate the characters in 10 (the t builtin) to the characters in 01.

• I'd say the first solution is fine, nicely done Mar 15 at 23:12

# Factor + pair-rocket, 25 bytes

[ "# "=> " #"substitute ]


Try it online!

# Vyxal, 1 byte

⌐


Try it Online!

Same method as DLosc's 3 byte Pip answer. Takes a list of lists of either 0 or 1.

Simply computes 1 - n for each digit. Alternatively,

## Vyxal, 3 bytes

₀S*


Try it Online!

Takes a multiline string of 0s and 1s. The flag, header and footer are for allowing the test cases to be directly pasted in without having to change them.

## Explained

₀S*
₀S  # The string "10"
* # Ring translate the input according to that - change 0 to 1, 1 to 0 and leave newlines as they are.


# 05AB1E, 1 byte

Each line is a separated potential program:

_
≠
È


I/O as a matrix of 1s and 0s.

Using the actual # and spaces as I/O, it would be 5 bytes instead:

„# Â‡


I/O as multiline strings with #s/spaces and potential newlines.

Explanation:

      # Transform each 1 to 0 and each 0 to 1 in the (implicit) input-matrix,
_     #  using an ==0 check
≠     #  or !=1 check
È     #  or %2==0 (is_even) check
# (after which the modified matrix is output implicitly)

„#    # Push string "# "
Â  # Bifurcate it, short for Duplicate & Reverse copy
‡ # Transliterate all "#" to " " and vice-versa in the (implicit) input
# (after which the modified string is output implicitly)


map g
g ' '='#'
g c=min ' 'c


Try it online!

Acts on a string with newlines in it.

By the same rules-lawyering as this Pip answer I guess map$map(1-) is a valid answer, but I don't really like it. # Octave, 13 bytes @(x)['' 67-x]  Try it online! Takes the input as an array of '# ' characters. The sum of '#' and ' ' is 67, so all we need to do is subtract the input string from 67 and it will "negate" the characters. Unfortunately we then have to spend a few bytes forcing the output back to being a character array rather than an integer, but ho hum. # R, 38 30 bytes Or 23 bytes by exchanging function for \ using R≥4.1: Attempt This Online! function(x)chartr("# "," #",x)  Try it online! • As of R 4.1.0 you can use a forward slash instead of "function" Mar 17 at 16:52 • @BillO'Brien - Yes, now specified, thanks. Mar 18 at 8:03 # Pyth, 13 bytes L:::bdN\#dN\#  Try it online! # APL+WIN, 32 bytes Prompts for m x n matrix n←(⍴m←⎕)⍴' '⋄((,m=' ')/,n)←'#'⋄n  Try it online! Thanks to Dyalog APL Classic # Retina 0.8.2, 6 bytes T10d  Try it online! Swaps 0 with 1 but link is to test suite that converts from  # to 01 and back. Explanation: d is shorthand for 0-9 or 0123456789 so this translates 1 to 0 and 0 to 1 (the extra target characters are ignored). # Charcoal, 8 bytes ＷＳ⟦⭆ι¬Σκ  Try it online! Link is to verbose version of code. Takes input as a list of newline-terminated strings of 0s and 1s. Explanation: ＷＳ  While there are more strings in the input... ⟦⭆ι¬Σκ  ... logically invert each character's decimal value and output the result on its own line. # Jelly, 4 bytes O^1Ọ  A monadic Link that accepts a list of lists of characters (from   and !) and yields a list of lists of characters with these characters swapped. Try it online! ### How? O^1Ọ - Link: list of lists of characters O - ordinal (vectorises) : ' ' -> 32 and '!' -> 33 1 - one : 1 ^ - XOR (vectorises) : 32 -> 33 and 33 -> 32 Ọ - character (vectorises) : 33 -> '!' and 32 -> ' '  If integers are allowed in place of characters as I/O then the one byte Link ¬ would suffice (vectorising loginal NOT). # Python 3, 21 bytes lambda s:s.swapcase()  Takes a multiline string consisting of a for spaces and A for #'s and outputs the string after swapping the case of each letter. Not quite as nice-looking (or interesting) as loopy walt's wonderful answer, but I'm happy to finally write an answer to one of these :) Try it online! • Swapping case is a really clever solution to this problem! Mar 18 at 17:22 • 12 bytes Mar 18 at 23:19 • ... and very clever, indeed. Mar 18 at 23:19 • @loopywalt ha! you win this round... Mar 19 at 4:47 # Vim, 3 bytes VG~  Your output characters must be the same as your input characters (e.g. ["#"," "] -> [" ","#"]), which you are free to choose (but must be printable characters) We will use the upper case and lower case version of any alphabetic character. ### Explanation 1. V: Select the whole line 2. G: Go to the end of the document 3. ~: Swap case of the characters Try it online! (Using: ["q","Q"] -> ["Q","q"]) Try it online! (Adding some replaces to fit the caracters in the examples) ## Batch, 60 bytes @set/ps= @set s=%s: =$%
@set s=%s:#= %
@echo(%s:$=#% @%0  Swaps spaces with #s. Doesn't work well with file input as it needs to be interrupted with Ctrl+C to exit. Explanation: @set/ps=  Read in the next line. @set s=%s: =$%


Replace the spaces with $s. @set s=%s:#= %  Replace the #s with spaces. @echo(%s:$=#%


Replace the \$s with #s and output the result.

@%0


Rinse and repeat.

Elisp + s.el, 57 bytes

(s-replace"-""#"(s-replace"#"" "(s-replace" ""-"(read))))


f l=[[x|c<-s,x<-"# ",x/=c]|s<-l]


Try it online!

Takes and returns a list of String

# brainfuck, 28 22 bytes

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


Try it online!

Switch *(42) and j(106). Long to make \n(10) same

# Vyxal, 1 byte

N


Try it Online!

A different Vyxal solution. Expects uppercase letters for # and lowercase letters for   or vice versa. N is the swap case element. The header and footer converts the test case format into the format that the program expects and vice versa.

# Ruby, 18 bytes

->s{s.tr"# "," #"}


Try it online!

I suggested this to fix a Ruby answer but disappeared..

# Husk, 6 bytes

†?_aD¶


Try it online!

Input & output as single multiline string; 'pixels' are 'A' and 'a' (or any other pair of uppercase & lowercase letters).

Split on newlines (¶), then, for each (†) character, if (?) it's uppercase (D) convert to lowercase (_), otherwise convert to uppercase (a).

If input is already list of strings, we can drop the ¶ for 5 bytes. If input is a list of integers (1 and zero) we can have 2 bytes.

• After running some tests, I can definitively say its all just yelling at me. Mar 16 at 16:12

# R, 14 bytes

-5 bytes by l4m2, using 1-m instead of abs(m-1) and +11 for providing the required function call.

function(m)1-m


Try it online!

I do personally dislike the freedom of I/O in this challenge and allowing any other input characters than " " and "#". I learned something new from Dominic van Essen's answer actually as I was never aware of that function. But bending the rules to make life easier, nevertheless my answer. Input a 0-1 matrix and just reverse the values.

• Why not 1-m? also you need to input
– l4m2
Mar 18 at 12:42
• yes 1-m would do, haha not sure why I made it more complex :D Anyhow, the input part what needs to be part of the count or not is perhaps my inexperience. To me it makes no sense that function(m) 1-m would be allowed while 1-m would not as in both scenario's m is the input ourside. Mar 18 at 12:51
• @MerijnvanTilborg - You need function(m)1-m because you cannot assume that a variable named 'm' has been defined outside your code: that would be what we call a 'snippet' (a non self-contained piece of code). Mar 18 at 13:04
• @MerijnvanTilborg ...although, of course, for maximal shortness you can choose to specify R≥4.1 and change to \(m)1-m... Mar 18 at 13:05
• Thanks both for the constructive feedback, I hope I managed to edit my answer to fix and give credits for the improvement. Mar 18 at 13:16

# Charcoal, 19 bytes

ＷＳ«Ｆι«≡κ ¦#¦ »Ｍ±Ｌι¹


Try it online!

• Ｆι←↓ saves a byte over Ｍ±Ｌι¹, and ≡κ#Ｍ→# saves another byte, although it does trim spaces from the right and bottom of the output. Or I guess using ψ instead of Ｍ→ works (ψ is the "erase" character).
– Neil
Mar 20 at 18:56

# Gema, 7 characters

%=.;.=%


For this version choose the % and . characters.

Try it online!

### Gema, 10 characters

\#=\ ;\ =#


This uses the original # and   characters. Unfortunately this needs escaping because

• # is metacharacter similar to * (.* in regex), but recursive
•   is metacharacter and means one or more whitespace characters (\s+ in regex)

Try it online!