26
\$\begingroup\$

Task

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:

 ##   ##  #######  ##       ##       #######      ##   ##  #######  #######  ##       ######  
 ##   ##  ##       ##       ##       ##   ##      ##   ##  ##   ##  ##   ##  ##       ##   ## 
 #######  #####    ##       ##       ##   ##      ## # ##  ##   ##  #######  ##       ##   ## 
 ##   ##  ##       ##       ##       ##   ##      ### ###  ##   ##  ## ##    ##       ##   ## 
 ##   ##  #######  #######  #######  #######      ##   ##  #######  ##   ##  #######  ######  
\$\endgroup\$
8
  • 1
    \$\begingroup\$ Duplicate, not sure which one \$\endgroup\$
    – Fmbalbuena
    Commented Mar 15, 2022 at 20:57
  • 32
    \$\begingroup\$ @Fmbalbuena if you can't find the duplicate then surely it isn't a duplicate? \$\endgroup\$
    – jezza_99
    Commented Mar 15, 2022 at 21:06
  • 3
    \$\begingroup\$ No, but I need help of someone to find the duplicate \$\endgroup\$
    – Fmbalbuena
    Commented Mar 15, 2022 at 21:11
  • 2
    \$\begingroup\$ @Fmbalbuena yeah I did have a look, but couldn't find anything \$\endgroup\$
    – jezza_99
    Commented Mar 15, 2022 at 21:13
  • 2
    \$\begingroup\$ 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|? \$\endgroup\$ Commented Mar 18, 2022 at 12:12

43 Answers 43

50
\$\begingroup\$

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.

\$\endgroup\$
7
  • 9
    \$\begingroup\$ oh wow this is clever!! I dont think I would have ever thought to multiply the string like that \$\endgroup\$
    – des54321
    Commented Mar 15, 2022 at 22:54
  • 2
    \$\begingroup\$ I'd love an explanation of how this works \$\endgroup\$
    – jezza_99
    Commented Mar 16, 2022 at 0:32
  • 3
    \$\begingroup\$ @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). \$\endgroup\$
    – Alon Amit
    Commented Mar 16, 2022 at 9:00
  • 3
    \$\begingroup\$ 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. \$\endgroup\$
    – Alon Amit
    Commented Mar 16, 2022 at 9:03
  • \$\begingroup\$ I daresay this could save a byte by using the rule that you can define your own input/output characters (except the newline) \$\endgroup\$
    – Dave
    Commented Mar 17, 2022 at 22:00
11
\$\begingroup\$

sed, 23 8 bytes

-15 bytes thanks to Digital Trauma

y/# / #/

Try it online!

\$\endgroup\$
1
  • 6
    \$\begingroup\$ Try y/# / #/ :) \$\endgroup\$ Commented Mar 15, 2022 at 21:27
8
\$\begingroup\$

C (tcc), 33 bytes

Function that modifies its input.

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

Try it online!

\$\endgroup\$
8
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ I'd say the first solution is fine, nicely done \$\endgroup\$
    – jezza_99
    Commented Mar 15, 2022 at 23:12
8
\$\begingroup\$

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
)
\$\endgroup\$
2
  • 1
    \$\begingroup\$ 1-i would also work, I assume. \$\endgroup\$
    – Neil
    Commented Mar 20, 2022 at 18:44
  • 1
    \$\begingroup\$ @Neil, Yes that also works. Probably a bit simpler, but no byte difference so I'll keep it as is. \$\endgroup\$ Commented Mar 20, 2022 at 21:33
7
\$\begingroup\$

Bash + coreutils, 12

tr '# ' ' #'

Try it online!

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

Lua, 68 bytes

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

Attempt This Online!

lol

\$\endgroup\$
6
\$\begingroup\$

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.

\$\endgroup\$
5
\$\begingroup\$

Factor + pair-rocket, 25 bytes

[ "# "=> " #"substitute ]

Try it online!

\$\endgroup\$
5
\$\begingroup\$

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. 
\$\endgroup\$
5
\$\begingroup\$

Haskell, 28 bytes

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.

\$\endgroup\$
5
\$\begingroup\$

05AB1E, 1 byte

Each line is a separated potential program:

_
≠
È

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

Try it online or verify all test cases.

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.

Try it online or verify all test cases.

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)
\$\endgroup\$
4
\$\begingroup\$

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

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

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!

\$\endgroup\$
2
  • \$\begingroup\$ As of R 4.1.0 you can use a forward slash instead of "function" \$\endgroup\$ Commented Mar 17, 2022 at 16:52
  • \$\begingroup\$ @BillO'Brien - Yes, now specified, thanks. \$\endgroup\$ Commented Mar 18, 2022 at 8:03
4
\$\begingroup\$

brainfuck, 28 22 bytes

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

Try it online!

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

\$\endgroup\$
3
\$\begingroup\$

Pyth, 13 bytes

L:::bdN\#dN\#

Try it online!

\$\endgroup\$
3
\$\begingroup\$

APL+WIN, 32 bytes

Prompts for m x n matrix

n←(⍴m←⎕)⍴' '⋄((,m=' ')/,n)←'#'⋄n

Try it online! Thanks to Dyalog APL Classic

\$\endgroup\$
3
\$\begingroup\$

Retina 0.8.2, 6 bytes

T`10`d

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

\$\endgroup\$
3
\$\begingroup\$

Charcoal, 8 bytes

WS⟦⭆ι¬Σκ

Try it online! Link is to verbose version of code. Takes input as a list of newline-terminated strings of 0s and 1s. Explanation:

WS

While there are more strings in the input...

⟦⭆ι¬Σκ

... logically invert each character's decimal value and output the result on its own line.

\$\endgroup\$
3
\$\begingroup\$

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.

\$\endgroup\$
5
  • 2
    \$\begingroup\$ Why not 1-m? also you need to input \$\endgroup\$
    – l4m2
    Commented Mar 18, 2022 at 12:42
  • \$\begingroup\$ 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. \$\endgroup\$ Commented Mar 18, 2022 at 12:51
  • 1
    \$\begingroup\$ @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). \$\endgroup\$ Commented Mar 18, 2022 at 13:04
  • 1
    \$\begingroup\$ @MerijnvanTilborg ...although, of course, for maximal shortness you can choose to specify R≥4.1 and change to \(m)1-m... \$\endgroup\$ Commented Mar 18, 2022 at 13:05
  • 1
    \$\begingroup\$ Thanks both for the constructive feedback, I hope I managed to edit my answer to fix and give credits for the improvement. \$\endgroup\$ Commented Mar 18, 2022 at 13:16
3
\$\begingroup\$

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!

\$\endgroup\$
4
  • 2
    \$\begingroup\$ Swapping case is a really clever solution to this problem! \$\endgroup\$
    – chunes
    Commented Mar 18, 2022 at 17:22
  • 3
    \$\begingroup\$ 12 bytes \$\endgroup\$
    – loopy walt
    Commented Mar 18, 2022 at 23:19
  • \$\begingroup\$ ... and very clever, indeed. \$\endgroup\$
    – loopy walt
    Commented Mar 18, 2022 at 23:19
  • \$\begingroup\$ @loopywalt ha! you win this round... \$\endgroup\$ Commented Mar 19, 2022 at 4:47
3
\$\begingroup\$

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)

\$\endgroup\$
3
\$\begingroup\$

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.

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

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.

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

Elisp + s.el, 57 bytes

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

enter image description here

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

Haskell, 32 bytes

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

Try it online!

Takes and returns a list of String

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

Ruby, 18 bytes

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

Try it online!

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

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

Charcoal, 19 bytes

WS«Fι«≡κ ¦#¦ »M±Lι¹

Try it online!

\$\endgroup\$
1
  • \$\begingroup\$ Fι←↓ saves a byte over M±Lι¹, and ≡κ#M→# saves another byte, although it does trim spaces from the right and bottom of the output. Or I guess using ψ instead of M→ works (ψ is the "erase" character). \$\endgroup\$
    – Neil
    Commented Mar 20, 2022 at 18:56
2
\$\begingroup\$

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!

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

MATL, 4 bytes

5\Zc

Input is a char matrix containing and #.

Try it online!

How it works

     % Implicit input
5\   % Modulo 5 of (codepoints) of the input chars. This gives 2 for space, 0 for '#'
Zc   % Convert nonzeros to '#' and zeros to char(0)
     % Implicit display. char(0) is displayed as a space
\$\endgroup\$
2
  • \$\begingroup\$ Congrats on 100k rep! \$\endgroup\$
    – naffetS
    Commented Aug 17, 2022 at 3:54
  • \$\begingroup\$ @Steffan Thank you! \$\endgroup\$
    – Luis Mendo
    Commented Aug 17, 2022 at 8:32

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