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

32 Answers 32

38
\$\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
  • 8
    \$\begingroup\$ oh wow this is clever!! I dont think I would have ever thought to multiply the string like that \$\endgroup\$
    – des54321
    Mar 15 at 22:54
  • 2
    \$\begingroup\$ I'd love an explanation of how this works \$\endgroup\$
    – jezza_99
    Mar 16 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
    Mar 16 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
    Mar 16 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
    Mar 17 at 22:00
10
\$\begingroup\$

sed, 23 8 bytes

-15 bytes thanks to Digital Trauma

y/# / #/

Try it online!

\$\endgroup\$
1
  • 4
    \$\begingroup\$ Try y/# / #/ :) \$\endgroup\$ Mar 15 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\$

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

Bash + coreutils, 12

tr '# ' ' #'

Try it online!

\$\endgroup\$
6
  • 2
    \$\begingroup\$ Apparently you can escape the leading space instead of quoting the second string: tr '# ' \ # \$\endgroup\$
    – ovs
    Mar 15 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
    Mar 15 at 22:33
  • \$\begingroup\$ @ovs You can also do tr #\ \ # \$\endgroup\$
    – iBug
    Mar 16 at 16:42
  • \$\begingroup\$ @iBug As Neil mentioned # starts a comment, so this only works if you use a different character than #. \$\endgroup\$
    – ovs
    Mar 16 at 16:49
  • 8
    \$\begingroup\$ if you define your characters as t and r you can use tr rt tr! \$\endgroup\$
    – Dave
    Mar 17 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\$

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
    Mar 15 at 23:12
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\$
5
\$\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\$
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\$ Mar 17 at 16:52
  • \$\begingroup\$ @BillO'Brien - Yes, now specified, thanks. \$\endgroup\$ Mar 18 at 8:03
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\$

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\$
3
\$\begingroup\$

brainfuck, 28 22 bytes

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

Try it online!

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

\$\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
    Mar 18 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\$ Mar 18 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\$ Mar 18 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\$ Mar 18 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\$ Mar 18 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
    Mar 18 at 17:22
  • 2
    \$\begingroup\$ 12 bytes \$\endgroup\$
    – loopy walt
    Mar 18 at 23:19
  • \$\begingroup\$ ... and very clever, indeed. \$\endgroup\$
    – loopy walt
    Mar 18 at 23:19
  • \$\begingroup\$ @loopywalt ha! you win this round... \$\endgroup\$ Mar 19 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\$

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
    Mar 20 at 18:56
1
\$\begingroup\$

Ruby, 18 bytes

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

Try it online!

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

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

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.

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

///, 55 bytes

/
 /
> //
#/
>#// #/ >#//# /#> //>#/->//> /#>//-/ //>//

Man, the underscore on the /// link looks bad. Ah, well.

Basically, we first put a cursor (>) before every run of hashes or spaces, then flip each character after a >. We need to use an intermediate character (-) to avoid flipping things twice.

Try it online!

\$\endgroup\$

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.