15
\$\begingroup\$

The Banach–Tarski paradox states that, given a ball in 3‑dimensional space, you can decompose the ball into a finite number of point subsets. These disjoint sets of points can then be reassembled to produce two copies of the initial ball. You would then, theoretically, have two identical balls.

The process of reassembly consists of only moving the aforementioned point subsets and rotating them, while not changing their spacial shape. This can be done with as few as five disjoint subsets.

Disjoint sets have no common elements by definition. Where A and B are any two point subsets of the initial ball, the common elements between A and B is an empty set. This is shown in the following equation.

LaTeX representation

For the disjoint sets below, the common members form an empty set.

LaTeX representation


The Challenge

Write a program that can take an input ASCII "ball", and output a duplicate "ball".


Input

Here is an example input ball:

      ##########      
   ###@%$*.&.%%!###   
  ##!$,%&?,?*?.*@!##  
 ##&**!,$%$@@?@*@&&## 
#@&$?@!%$*%,.?@?.@&@,#
#,..,.$&*?!$$@%%,**&&#
 ##.!?@*.%?!*&$!%&?## 
  ##!&?$?&.!,?!&!%##  
   ###,@$*&@*,%*###   
      ##########      

Each sphere is outlined by pound signs (#) and filled with any of theses characters: .,?*&$@!%. Every input will be a 22x10 characters (width by height).


Creating a Duplicate

First, each point inside the ball is given a numbered point based on its index in .,?*&$@!%. Here is the above example, once numbered:

      ##########      
   ###7964151998###   
  ##86295323431478##  
 ##5448269677374755## 
#75637896492137317572#
#21121654386679924455#
 ##1837419384568953## 
  ##85363518238589##  
   ###2764574294###   
      ##########      

Then, each point is shifted up one (nine goes to one):

      ##########      
   ###8175262119###   
  ##97316434542589##  
 ##6559371788485866## 
#86748917513248428683#
#32232765497781135566#
 ##2948521495679164## 
  ##96474629349691##  
   ###3875685315###   
      ##########      

Finally, each new point value is converted back to its corresponding character:

      ##########      
   ###!.@&,$,..%###   
  ##%@?.$*?*&*,&!%##  
 ##$&&%?@.@!!*!&!$$## 
#!$@*!%.@&.?,*!*,!$!?#
#?,,?,@$&*%@@!..?&&$$#
 ##,%*!&,.*%&$@%.$*## 
  ##%$*@*$,%?*%$%.##  
   ###?!@&$!&?.&###   
      ##########      

Output

These two balls are then output side-by-side, in this form (separated by four spaces at the equators):

      ##########                ##########      
   ###@%$*.&.%%!###          ###!.@&,$,..%###   
  ##!$,%&?,?*?.*@!##        ##%@?.$*?*&*,&!%##  
 ##&**!,$%$@@?@*@&&##      ##$&&%?@.@!!*!&!$$## 
#@&$?@!%$*%,.?@?.@&@,#    #!$@*!%.@&.?,*!*,!$!?#
#,..,.$&*?!$$@%%,**&&#    #?,,?,@$&*%@@!..?&&$$#
 ##.!?@*.%?!*&$!%&?##      ##,%*!&,.*%&$@%.$*## 
  ##!&?$?&.!,?!&!%##        ##%$*@*$,%?*%$%.##  
   ###,@$*&@*,%*###          ###?!@&$!&?.&###   
      ##########                ##########      

Note: Shifting the point values, and later characters, is symbolic of the rotations performed to reassemble the point subsets (character groupings).

\$\endgroup\$
5
  • \$\begingroup\$ Does it have to be adjacent? can they be outputed above each others? \$\endgroup\$
    – Mohammad
    Sep 29, 2015 at 19:13
  • \$\begingroup\$ They must be adjacent. The two 22x10 blocks should be horizontally separated by 4 spaces. @Mhmd \$\endgroup\$
    – Zach Gates
    Sep 29, 2015 at 19:15
  • \$\begingroup\$ Functions are allowed in your program. The program must execute on its own, though (with a user input). @ETHproductions \$\endgroup\$
    – Zach Gates
    Sep 29, 2015 at 19:27
  • \$\begingroup\$ Shouldn't both balls be rotated? As I understand the theorem, the original doesn't stay, but you get two new balls. \$\endgroup\$ Sep 30, 2015 at 8:42
  • \$\begingroup\$ Yes, but an answer had been submitted before I got the chance to make that edit, and I didn't want to invalidate any solutions. @PaŭloEbermann \$\endgroup\$
    – Zach Gates
    Sep 30, 2015 at 11:42

13 Answers 13

7
\$\begingroup\$

Pyth, 21 bytes

#++Jw*4d.rJ".,?*&$@!%

Try it online: Demonstration

Finally a use-case for .r.

Explanation

#++Jw*4d.rJ".,?*&$@!%
#                       infinite loop
   Jw                   read a string from input and store it in J
     *4d                4 spaces
        .rJ".,?*&$@!%   rotate the chars of J using this char order
 ++                     combine the 3 strings (J, spaces, rotated) and print

The infinite loop breaks, when there is no more input available.

\$\endgroup\$
7
\$\begingroup\$

Ruby, 65

10.times{b=gets;puts b.chop.tr(',?*&$@!%.','.,?*&$@!%')+'    '+b}

Works great when input is taken from a file instead of stdin:

ruby banach.rb < ball.txt
    

On the other hand, if you like typing in balls to stdin manually, and want the output at the end, try this 67-byte version:

puts (0..9).map{b=gets;b.chop.tr(',?*&$@!%.','.,?*&$@!%')+'    '+b}
\$\endgroup\$
6
\$\begingroup\$

Matlab, 120

Matlab is not the greatest language for handling strings. \n is always considered as two characters, which is quite annoying, and you cannot just make a matrix out of a line-breaked (line-broken?) string, you have to do it manually. At least I did not have to care about the size/padding as every line has the exact same length.

a='.,?*&$@!%.';b=input('');b(b>90)=[];b=reshape(b',22,10)';c=b;for k=1:9;c(b==a(k))=a(k+1);end;disp([b,ones(10,4)*32,c])

Example Input:

'      ##########      \n   ###@%$*.&.%%!###   \n  ##!$,%&?,?*?.*@!##  \n ##&**!,$%$@@?@*@&&## \n#@&$?@!%$*%,.?@?.@&@,#\n#,..,.$&*?!$$@%%,**&&#\n ##.!?@*.%?!*&$!%&?## \n  ##!&?$?&.!,?!&!%##  \n   ###,@$*&@*,%*###   \n      ##########      '

Example output:

      ##########                ##########      
   ###@%$*.&.%%!###          ###!.@&,$,..%###   
  ##!$,%&?,?*?.*@!##        ##%@?.$*?*&*,&!%##  
 ##&**!,$%$@@?@*@&&##      ##$&&%?@.@!!*!&!$$## 
#@&$?@!%$*%,.?@?.@&@,#    #!$@*!%.@&.?,*!*,!$!?#
#,..,.$&*?!$$@%%,**&&#    #?,,?,@$&*%@@!..?&&$$#
 ##.!?@*.%?!*&$!%&?##      ##,%*!&,.*%&$@%.$*## 
  ##!&?$?&.!,?!&!%##        ##%$*@*$,%?*%$%.##  
   ###,@$*&@*,%*###          ###?!@&$!&?.&###   
      ##########                ##########      

PS: If I can assume the input this way:

['      ##########      ','   ###@%$*.&.%%!###   ','  ##!$,%&?,?*?.*@!##  ',' ##&**!,$%$@@?@*@&&## \n#@&$?@!%$*%,.?@?.@&@,#','#,..,.$&*?!$$@%%,**&&#',' ##.!?@*.%?!*&$!%&?## ','  ##!&?$?&.!,?!&!%##  ','   ###,@$*&@*,%*###   ','      ##########      ']

I only need 88 characters:

a='.,?*&$@!%.';b=input('');c=b;for k=1:9;c(b==a(k))=a(k+1);end;disp([b,ones(10,4)*32,c])
\$\endgroup\$
4
\$\begingroup\$

Ruby, 102

IO.readlines(?a).map(&:chomp).each{|x|puts"#{x+' '*x.count(' ')+?\s*4+x.tr('.,?*&$@!%',',?*&$@!%.')}"}

Basically, its just calling tr on the input

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

sed (39 bytes)

h;y/.,?*&$@!%/,?*&$@!%./;H;x;s/\n/    /
\$\endgroup\$
4
\$\begingroup\$

CJam, 28 bytes

qN/{_".,?*&$@!%"_(+erS4*\N}%

Try it online

Explanation:

qN/     Get input and split into lines.
{       Start loop over lines.
  _       Copy, since we need to output original.
  ".,?*&$@!%"
          List of characters, in order.
  _       Copy list of characters.
  (+      Rotate the list by popping first character and appending it.
  er      Transliterate.
  S4*     Create 4 spaces.
  \       Swap spaces between original and transliteration.
  N       Add newline.
}%      End of loop over lines.
\$\endgroup\$
4
\$\begingroup\$

Python 3.5, 96 89 88 bytes

s='.,?*&$@!%.  ##';i=1
while i:i=input();print(i,'  ',''.join(s[s.find(y)+1]for y in i))

Python 3.3, 103 96 95 bytes

s='.,?*&$@!%.  ##'
for i in input().split('\n'):print(i,'  ',''.join(s[s.find(y)+1]for y in i))

Explanation

Python 3.3 and 3.5 are listed separately because the way input() handles newlines in IDLE changed. This happened to save 8 bytes, which is cool.

Note on execution: use IDLE. If you use a terminal, then the solution for 3.3 is the same as 3.5, but both interleave the input with the output.

I reversed the symbol string s to take advantage of Python's negative indexing. Then for each line in the input, I output it, two spaces, and the line with each symbol replaced with its preceding symbol. The reason I only put two spaces is that I used , instead of +, which adds a space to the printed output. This (,' ',) saved me a byte over +' '*4+.

Thanks to xsot for saving me 7 8 bytes. I changed s.find to s.rfind to allow me to put the spaces and hashes into s, thereby removing the need to do a check for y in s. Plus, a space was saved. EDIT: changed back to s.find because the presence of ## now allows me to +1 without worrying about an index-out-of-bounds error.

\$\endgroup\$
9
  • \$\begingroup\$ Would you mind explaining how input() changed? I can't find any differences between the 3.4 and 3.5 documentation. \$\endgroup\$
    – Kevin
    Sep 30, 2015 at 1:10
  • \$\begingroup\$ Newlines in the input string "terminate" the input, so to speak, and re-call your input code. In Python 3.3, newlines are passed in intact. The change must be between 3.3 and 3.4. \$\endgroup\$ Sep 30, 2015 at 1:56
  • \$\begingroup\$ Nope, the 3.3 docs are the same too. I'm guessing this is a readline change, probably from a version bump. If you compile without readline, you might not notice any difference. \$\endgroup\$
    – Kevin
    Sep 30, 2015 at 2:58
  • \$\begingroup\$ I use IDLE, so it may also be at fault. I'll try running it from a terminal. \$\endgroup\$ Sep 30, 2015 at 3:03
  • \$\begingroup\$ @Kevin: How interesting. From the command line, it works properly in 3.5 although the input is interleaved with the output. For 3.3, it breaks immediately after the first newline. I copy-pasted the text whole. \$\endgroup\$ Sep 30, 2015 at 3:56
3
\$\begingroup\$

Retina, 45 39 bytes

.+
$0  ; $0
T`.,?*&$@!%;`,?*&$@!%. `;.*

To run the code from a single file, use the -s flag.

The first stage duplicates each line, separated by " ; ", to get

      ##########        ;       ##########
   ###@%$*.&.%%!###     ;    ###@%$*.&.%%!###
  ##!$,%&?,?*?.*@!##    ;   ##!$,%&?,?*?.*@!##
 ##&**!,$%$@@?@*@&&##   ;  ##&**!,$%$@@?@*@&&##
#@&$?@!%$*%,.?@?.@&@,#  ; #@&$?@!%$*%,.?@?.@&@,#
#,..,.$&*?!$$@%%,**&&#  ; #,..,.$&*?!$$@%%,**&&#
 ##.!?@*.%?!*&$!%&?##   ;  ##.!?@*.%?!*&$!%&?##
  ##!&?$?&.!,?!&!%##    ;   ##!&?$?&.!,?!&!%##
   ###,@$*&@*,%*###     ;    ###,@$*&@*,%*###
      ##########        ;       ##########

Then the second stage only affects characters which are found in matches of ;.*, i.e. only the second half of each line. Those characters are then transliterated via the following correspondence

.,?*&$@!%;
,?*&$@!%. 

Where the first 9 pairs "increment" the characters in the ball and the last pair turns the semicolon into another space.

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

Vyxal ja, 22 bytes

ƛ:`.,?*&$@!%`:ǓĿð4*$++

Try it Online!

a flag makes Vyxal take all newline-separated inputs as a list.

ƛ                      # Map...
 `.,?*&$@!%`           # The characters
            :ǓĿ        # Transliterate input by chars and chars shifted
               ?ð4*+   # Add four spaces to each line of the original
                    $+ # Add the previous, with chars shifted

-1 thanks to Razetime

\$\endgroup\$
2
  • \$\begingroup\$ -1: ƛ:`.,?*&$@!%`:ǓĿð4*$++ \$\endgroup\$
    – Razetime
    Jun 14, 2021 at 6:29
  • \$\begingroup\$ @Razetime Nice!' \$\endgroup\$
    – emanresu A
    Jun 14, 2021 at 8:48
2
\$\begingroup\$

Python 2, 77 bytes

while 1:r=raw_input();print r,'  ',r.translate(' % #@.$   & ? , '*3+'!*'*104)
\$\endgroup\$
2
\$\begingroup\$

Perl, 59 bytes

56 bytes code plus 3 bytes for -p as this needs to be saved to a file.

chop($s=$_);$l=',?*&$@!%';eval"y/.$l/$l./";$_="$s    $_"

Example usage:

$perl -p ball.pl <<< '      ##########      
>    ###@%$*.&.%%!###   
>   ##!$,%&?,?*?.*@!##  
>  ##&**!,$%$@@?@*@&&## 
> #@&$?@!%$*%,.?@?.@&@,#
> #,..,.$&*?!$$@%%,**&&#
>  ##.!?@*.%?!*&$!%&?## 
>   ##!&?$?&.!,?!&!%##  
>    ###,@$*&@*,%*###   
>       ##########      
> '
      ##########                ##########      
   ###@%$*.&.%%!###          ###!.@&,$,..%###   
  ##!$,%&?,?*?.*@!##        ##%@?.$*?*&*,&!%##  
 ##&**!,$%$@@?@*@&&##      ##$&&%?@.@!!*!&!$$## 
#@&$?@!%$*%,.?@?.@&@,#    #!$@*!%.@&.?,*!*,!$!?#
#,..,.$&*?!$$@%%,**&&#    #?,,?,@$&*%@@!..?&&$$#
 ##.!?@*.%?!*&$!%&?##      ##,%*!&,.*%&$@%.$*## 
  ##!&?$?&.!,?!&!%##        ##%$*@*$,%?*%$%.##  
   ###,@$*&@*,%*###          ###?!@&$!&?.&###   
      ##########                ##########      
\$\endgroup\$
1
\$\begingroup\$

05AB1E (legacy), 21 bytes

|ʒD4ú".,?*&$@!%"DÀ‡«,

Uses the legacy version of 05AB1E, because it was possible to use the filter ʒ with implicit y as a foreach to print, whereas with the new version the actual for-each loop v with explicit y should be used, which is 1 byte longer.

Try it online.

Explanation:

|                      # Get the input-lines as list
 ʒ                     # For-each over the lines to print using the filter-builtin:
  D                    #  Duplicate the current line
   4ú                  #  Prepend 4 spaces to this copy
     ".,?*&$@!%"       #  Push this string
                DÀ     #  Duplicate it, and rotate its copy once towards the left
                  ‡    #  Transliterate the space-prepended string with these two strings
                   «   #  Append it to the original duplicated line
                    ,  #  And print with trailing newlines

Here a version that also works in the new version of 05AB1E (credit to @Grimy):

05AB1E, 21 bytes

TFD?4ú".,?*&$@!%"DÀ‡,

Try it online.

Explanation:

TF                     # Loop 10 times:
  D                    #  Duplicate the (implicit) input-line
   ?                   #  Pop and print the copy without trailing newline
    4ú                 #  Prepend 4 spaces to the input-line
      ".,?*&$@!%"      #  Push this string
                 DÀ    #  Duplicate it, and rotate its copy once towards the left
                   ‡   #  Transliterate the space-prepended string with these two strings
                    ,  #  And print with trailing newlines
\$\endgroup\$
2
  • 1
    \$\begingroup\$ Non-legacy 21: TFD?4ú".,?*&$@!%"DÀ‡, (input is guaranteed to be exactly 10 lines). \$\endgroup\$
    – Grimmy
    May 28, 2019 at 14:23
  • 1
    \$\begingroup\$ @Grimy Will add it as well. Also found that ₂j is a nice (although same byte) alternative for , since the width is guaranteed to be 26 characters. :) \$\endgroup\$ May 28, 2019 at 14:32
0
\$\begingroup\$

Stax, 16 bytes

âìè╩Jù╠╕╜☻u$1∞;ⁿ

Run and debug it

just a simple ring translation. Takes the input directly through STDIN.

\$\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.