16
\$\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\$
  • \$\begingroup\$ Does it have to be adjacent? can they be outputed above each others? \$\endgroup\$ – Mhmd Sep 29 '15 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 '15 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 '15 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\$ – Paŭlo Ebermann Sep 30 '15 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 '15 at 11:42

11 Answers 11

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.

| improve this answer | |
\$\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}
| improve this answer | |
\$\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])
| improve this answer | |
\$\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

| improve this answer | |
\$\endgroup\$
4
\$\begingroup\$

sed (39 bytes)

h;y/.,?*&$@!%/,?*&$@!%./;H;x;s/\n/    /
| improve this answer | |
\$\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.
| improve this answer | |
\$\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.

| improve this answer | |
\$\endgroup\$
  • \$\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 '15 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\$ – El'endia Starman Sep 30 '15 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 '15 at 2:58
  • \$\begingroup\$ I use IDLE, so it may also be at fault. I'll try running it from a terminal. \$\endgroup\$ – El'endia Starman Sep 30 '15 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\$ – El'endia Starman Sep 30 '15 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.

| improve this answer | |
\$\endgroup\$
2
\$\begingroup\$

Python 2, 77 bytes

while 1:r=raw_input();print r,'  ',r.translate(' % #@.$   & ? , '*3+'!*'*104)
| improve this answer | |
\$\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 <<< '      ##########      
>    ###@%$*.&.%%!###   
>   ##!$,%&?,?*?.*@!##  
>  ##&**!,$%$@@?@*@&&## 
> #@&$?@!%$*%,.?@?.@&@,#
> #,..,.$&*?!$$@%%,**&&#
>  ##.!?@*.%?!*&$!%&?## 
>   ##!&?$?&.!,?!&!%##  
>    ###,@$*&@*,%*###   
>       ##########      
> '
      ##########                ##########      
   ###@%$*.&.%%!###          ###!.@&,$,..%###   
  ##!$,%&?,?*?.*@!##        ##%@?.$*?*&*,&!%##  
 ##&**!,$%$@@?@*@&&##      ##$&&%?@.@!!*!&!$$## 
#@&$?@!%$*%,.?@?.@&@,#    #!$@*!%.@&.?,*!*,!$!?#
#,..,.$&*?!$$@%%,**&&#    #?,,?,@$&*%@@!..?&&$$#
 ##.!?@*.%?!*&$!%&?##      ##,%*!&,.*%&$@%.$*## 
  ##!&?$?&.!,?!&!%##        ##%$*@*$,%?*%$%.##  
   ###,@$*&@*,%*###          ###?!@&$!&?.&###   
      ##########                ##########      
| improve this answer | |
\$\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
| improve this answer | |
\$\endgroup\$
  • 1
    \$\begingroup\$ Non-legacy 21: TFD?4ú".,?*&$@!%"DÀ‡, (input is guaranteed to be exactly 10 lines). \$\endgroup\$ – Grimmy May 28 '19 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\$ – Kevin Cruijssen May 28 '19 at 14:32

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.