25
\$\begingroup\$

The Cheela (from the book Dragon's Egg by Robert L. Forward) are creatures that live on the surface of a neutron star. Their body is flat and circular with twelve eyes on the perimeter, so they naturally use a base-12 numbering system.

Among the Cheela, care of the hatchlings and education of the young are tasks carried out by the Old Ones. Since young Cheela need to be taught how to multiply, the Old Ones could use a multiplication table.

Your task is to produce a 12x12 multiplication table in base 12, like the following. Uppercase letters A and B are used for digits corresponding to decimal 10 and 11 respectively.

  1   2   3   4   5   6   7   8   9   A   B  10 
  2   4   6   8   A  10  12  14  16  18  1A  20 
  3   6   9  10  13  16  19  20  23  26  29  30 
  4   8  10  14  18  20  24  28  30  34  38  40 
  5   A  13  18  21  26  2B  34  39  42  47  50 
  6  10  16  20  26  30  36  40  46  50  56  60 
  7  12  19  24  2B  36  41  48  53  5A  65  70 
  8  14  20  28  34  40  48  54  60  68  74  80 
  9  16  23  30  39  46  53  60  69  76  83  90 
  A  18  26  34  42  50  5A  68  76  84  92  A0 
  B  1A  29  38  47  56  65  74  83  92  A1  B0 
 10  20  30  40  50  60  70  80  90  A0  B0 100

The output shoud be printed on screen. The format should be as follows:

  1. Numbers should be aligned to the right within each column.
  2. Leading spaces before the first column, trailing spaces after the last column, or a trailing new line after the last row are allowed.
  3. Separation between columns can be one space (as shown above) or more than one space, but the number of spaces should be consistent between columns. To measure column separation, consider that displayed numbers include any leading spaces that may have been necessary fo fulfill requirement 1 (so each number occupies three characters, the first of which may be spaces). For example, the table with two-space separation would be as follows:

      1    2    3    4    5    6    7    8    9    A    B   10 
      2    4    6    8    A   10   12   14   16   18   1A   20 
      3    6    9   10   13   16   19   20   23   26   29   30 
      4    8   10   14   18   20   24   28   30   34   38   40 
      5    A   13   18   21   26   2B   34   39   42   47   50 
      6   10   16   20   26   30   36   40   46   50   56   60 
      7   12   19   24   2B   36   41   48   53   5A   65   70 
      8   14   20   28   34   40   48   54   60   68   74   80 
      9   16   23   30   39   46   53   60   69   76   83   90 
      A   18   26   34   42   50   5A   68   76   84   92   A0 
      B   1A   29   38   47   56   65   74   83   92   A1   B0 
     10   20   30   40   50   60   70   80   90   A0   B0  100
    

Computer storage on a neutron star is really expensive, so your code should use as few bytes as possible.

Extended challenge and bonus

Ideally your code should be reused in other parts of the universe, where other numbering systems may be in use. To that end, the challenge is optionally extended as follows: Your code accepts a number N as input and generates an NxN multiplication table in base N, with the above format.

Input may be from keyboard or as a function argument. The program or function should work for 2N36, using as digits the first N characters of the sequence 0, 1, ..., 9, A, B, ..., Z (uppercase letters)

This extended challenge is optional. If you follow this route, take 20% off your byte count (no need to round to an integer number).

\$\endgroup\$
6
  • \$\begingroup\$ Nice one Luis! =) I wish I had the time to come up with a MATLAB solution, but I'm busy measuring Christmas gift dimensions... \$\endgroup\$ Commented Dec 20, 2015 at 18:23
  • 6
    \$\begingroup\$ Good luck with those spherical hats! :-P \$\endgroup\$
    – Luis Mendo
    Commented Dec 20, 2015 at 18:26
  • 6
    \$\begingroup\$ Because they have twelve eyes, they naturally use a base-12 numbering system. Well, naturally. That's why we use binary, after all... ;-) \$\endgroup\$ Commented Dec 21, 2015 at 13:34
  • 3
    \$\begingroup\$ @TimPederick Good point :-D To clarify: the body of a Cheela is circular, they can reshape limbs as needed... having twelve eyes is numerically the most distinct feature of their bodies. I've updated the question, thanks! \$\endgroup\$
    – Luis Mendo
    Commented Dec 21, 2015 at 13:44
  • 1
    \$\begingroup\$ @LuisMendo very nice novel, the one you quote. Starquake isn't bad either. \$\endgroup\$
    – lstefano
    Commented Jun 28, 2016 at 16:10

18 Answers 18

14
\$\begingroup\$

Pyth, 27 * 0.8 = 21.6

VSQsm.[\ 4jkXj*dNQrT99rG1SQ

Try it online: Demonstration

Explanation:

VSQsm.[\ 4jkXj*dNQrT99rG1SQ   implicit: Q = input number
VSQ                           for N in [1, 2, ..., Q]:
    m                    SQ      map each number d in [1, 2, ..., Q] to:
              *dN                   N * d
             j   Q                  in base Q
            X     rT99rG1           replace the numbers [10, 11, ..., 98] with "A...Z"
          jk                        join to a string
     .[\ 4                          prepend spaces, so that the string has a length of 4
   s                             join all strings and print
\$\endgroup\$
11
\$\begingroup\$

CJam, 33 * 0.8 = 26.4 bytes

ri:C,:)_ff{*Cb{_9>{'7+}&}%4Se[}N*

Test it here.

This uses the minimum required separation.

Explanation

ri:C        e# Read input, convert to integer, store in C.
,:)         e# Get range [1 2 ... C].
_ff{        e# 2D-map over all repeated pairs from that range...
  *Cb       e#   Multiply, convert to base C.
  {         e#   Map over the digits...
    _9>     e#     Check if the digit is greater than 9.
    {'7+}&  e#     If so, add the digit to the character "7", to get "A" to "Z".
  }%
  4Se[      e#   Pad the digits with spaces from the left, to 4 elements.
}
N*          e# Join with linefeeds.

Table for input 22 (the largest that fits in the post without a horizontal scrollbar):

   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F   G   H   I   J   K   L  10
   2   4   6   8   A   C   E   G   I   K  10  12  14  16  18  1A  1C  1E  1G  1I  1K  20
   3   6   9   C   F   I   L  12  15  18  1B  1E  1H  1K  21  24  27  2A  2D  2G  2J  30
   4   8   C   G   K  12  16  1A  1E  1I  20  24  28  2C  2G  2K  32  36  3A  3E  3I  40
   5   A   F   K  13  18  1D  1I  21  26  2B  2G  2L  34  39  3E  3J  42  47  4C  4H  50
   6   C   I  12  18  1E  1K  24  2A  2G  30  36  3C  3I  42  48  4E  4K  54  5A  5G  60
   7   E   L  16  1D  1K  25  2C  2J  34  3B  3I  43  4A  4H  52  59  5G  61  68  6F  70
   8   G  12  1A  1I  24  2C  2K  36  3E  40  48  4G  52  5A  5I  64  6C  6K  76  7E  80
   9   I  15  1E  21  2A  2J  36  3F  42  4B  4K  57  5G  63  6C  6L  78  7H  84  8D  90
   A   K  18  1I  26  2G  34  3E  42  4C  50  5A  5K  68  6I  76  7G  84  8E  92  9C  A0
   B  10  1B  20  2B  30  3B  40  4B  50  5B  60  6B  70  7B  80  8B  90  9B  A0  AB  B0
   C  12  1E  24  2G  36  3I  48  4K  5A  60  6C  72  7E  84  8G  96  9I  A8  AK  BA  C0
   D  14  1H  28  2L  3C  43  4G  57  5K  6B  72  7F  86  8J  9A  A1  AE  B5  BI  C9  D0
   E  16  1K  2C  34  3I  4A  52  5G  68  70  7E  86  8K  9C  A4  AI  BA  C2  CG  D8  E0
   F  18  21  2G  39  42  4H  5A  63  6I  7B  84  8J  9C  A5  AK  BD  C6  CL  DE  E7  F0
   G  1A  24  2K  3E  48  52  5I  6C  76  80  8G  9A  A4  AK  BE  C8  D2  DI  EC  F6  G0
   H  1C  27  32  3J  4E  59  64  6L  7G  8B  96  A1  AI  BD  C8  D3  DK  EF  FA  G5  H0
   I  1E  2A  36  42  4K  5G  6C  78  84  90  9I  AE  BA  C6  D2  DK  EG  FC  G8  H4  I0
   J  1G  2D  3A  47  54  61  6K  7H  8E  9B  A8  B5  C2  CL  DI  EF  FC  G9  H6  I3  J0
   K  1I  2G  3E  4C  5A  68  76  84  92  A0  AK  BI  CG  DE  EC  FA  G8  H6  I4  J2  K0
   L  1K  2J  3I  4H  5G  6F  7E  8D  9C  AB  BA  C9  D8  E7  F6  G5  H4  I3  J2  K1  L0
  10  20  30  40  50  60  70  80  90  A0  B0  C0  D0  E0  F0  G0  H0  I0  J0  K0  L0 100
\$\endgroup\$
0
8
\$\begingroup\$

MATL, 42*.8 = 33.6

Disclaimer

Since the creator of the language and the author of the challenge are the same, this answer is not eligible for winning.

For a discussion on whether this restriction is necessary or not, see this meta question.

Code

iXK:t!*Y)KYAZ{'(?<=^0*)0'32cYXZc32hK4*[]e!

This uses the minimum separation.

Example

Octal multiplication table

>> matl
 > iXK:t!*Y)KYAZ{'(?<=^0*)0'32cYXZc32chK4*[]e!
 > 
> 8
  1   2   3   4   5   6   7  10 
  2   4   6  10  12  14  16  20 
  3   6  11  14  17  22  25  30 
  4  10  14  20  24  30  34  40 
  5  12  17  24  31  36  43  50 
  6  14  22  30  36  44  52  60 
  7  16  25  34  43  52  61  70 
 10  20  30  40  50  60  70 100 

Explanation

i              % input number, say n
XK             % copy to clipboard K
:              % vector 1, 2, ... n
t!*            % generate table: duplicate, transpose and multiply with broadcasting
Y)             % linearize into column array
KYA            % paste n from clipboard K. Convert to that base
Z{             % cell array of rows from array
'(?<=^0*)0'    % string literal for regexp replacement: find leading zeros
32c            % space character (for regexp replacement)
YX             % regexp replacement
Zc             % join cell array of strings into single string   
32             % code for space character. Conversion to char happens automatically
h              % concatenate horizontally
K4*[]e!        % paste n and multiply by 4. Reshape into 2D char array with 4*n columns

Edit: Try it online!

To run in the online compiler (as of February 19, 2016), change Y) to X:, and remove []. This is to adapt to changes that have been made to the language since this challenge was posted.

\$\endgroup\$
5
  • \$\begingroup\$ "Since the creator of the language and the author of the challenge are the same, this answer is not eligible for winning." I wasn't aware of this restriction. Is this self-imposed or did you find a relevant meta consensus? \$\endgroup\$
    – Alex A.
    Commented Dec 20, 2015 at 19:18
  • 1
    \$\begingroup\$ @AlexA. I self-imposed it. I suspected there probably was some kind of agreement regarding that. From your commnent I see there isn't there any? My point is: if you design a language and then post a challenge, you are probably at an advantageous position. What's usually done about that? Not any restriction? \$\endgroup\$
    – Luis Mendo
    Commented Dec 20, 2015 at 19:21
  • \$\begingroup\$ I would think you aren't necessarily at an advantage so long as you don't plan a challenge specifically as a use case for a built-in in your language. I don't know of any such consensus offhand, so I recommend asking on meta. \$\endgroup\$
    – Alex A.
    Commented Dec 20, 2015 at 19:24
  • \$\begingroup\$ @AlexA. Good idea! Done \$\endgroup\$
    – Luis Mendo
    Commented Dec 20, 2015 at 19:35
  • \$\begingroup\$ @AlexA. If you feel like doing it, maybe add your suggestion as an answer there? \$\endgroup\$
    – Luis Mendo
    Commented Dec 20, 2015 at 19:40
5
\$\begingroup\$

Bash + BSD utilities, 36

echo Co{1..12}d{1..12}*p|dc|rs -j 12

Works out-of-the-box on OS X. rs may need to be installed on Linux systems.

  • Bash expands Co{1..12}d{1..12}*p to Co1d1*p Co1d2*p Co1d3*p ... Co1d12*p ... Co12d12*p.
  • This is a dc expression that generates the required terms. Co sets output base to 12. d is used as a separator between numbers instead of a space, so no escape is required in the brace expansion. d actually duplicates the top of stack, but this is effectively ignored and discarded.
  • The output from dc is a single space-separated line. rs reshapes this to a 12x12 array. -j right-justifies each term.
\$\endgroup\$
4
\$\begingroup\$

Pyth, 36 bytes

Km+1dUJ12rjbmjkm.[\ 4j""m.Hbj*dkJKK1

Try it here.

\$\endgroup\$
1
  • \$\begingroup\$ You can replace Km+1dUJ12 with KSJ12. S creates the range [1, 2, ..., 12]. You can replace both j"" and jk with s, since your joining strings. And another byte: Change rjbm...K1 to jmr...1K. With this changes you get 28 bytes: KSJ12jmrsm.[\ 4sm.Hbj*dkJK1K \$\endgroup\$
    – Jakube
    Commented Dec 20, 2015 at 18:12
4
\$\begingroup\$

Python, 153 147 132 bytes * 0.8 = 105.6

def p(b):
 f=lambda n:(n>=b and f(n/b)or'')+chr((48,55)[n%b>9]+n%b)
 for i in range(b*b):print'%4s\n'[:3+(~i%b<1)]%f(~(i%b)*~(i/b)),

Down to 132 bytes thanks to the advice of Tim Pederick! :)

\$\endgroup\$
6
  • \$\begingroup\$ Upvoted, because the more I golf my answer, the more it starts to look like yours! \$\endgroup\$ Commented Dec 21, 2015 at 6:07
  • \$\begingroup\$ Some possible improvements: Use %-formatting instead of rjust ('%4s'%f(...)). See whether printing each value with print ..., (and then one print for the newline) is shorter than join. If so, try collapsing the loops. \$\endgroup\$ Commented Dec 21, 2015 at 12:06
  • \$\begingroup\$ Thanks Tim, I tried collapsing the loops (I didn't know this trick). I'm not sure it makes me gain many bytes if any but it's pretty cool :) \$\endgroup\$ Commented Dec 21, 2015 at 12:33
  • \$\begingroup\$ I see you switched to a ternary form (condition and A or B) inside function f, using n>=b. I did that until I realised that it was no shorter than what I had before, n//b... but you're using Python 2! You can save a byte with n/b. \$\endgroup\$ Commented Dec 21, 2015 at 12:39
  • \$\begingroup\$ Yes that's the reason I used this part of your code exploiting python 2 to save one more byte :) \$\endgroup\$ Commented Dec 21, 2015 at 12:40
4
\$\begingroup\$

CJam, 38 33 32 38 * (.8) = 30.4 bytes

qi:D,:):L{Lf*{Db{_9>{55+c}&}%4Se[}%N}%

Try it here.

(Looks pretty similar to Martin's now.)

qi:D,:):L          e# Generate list of [1...input]
{Lf*               e# Take each number in that list and multiply it by the same list ([[1,2,3,..,input][2,4,6,...,input],...})
{Db{_9>{55+c}&}%   e# Convert each product to base input. If a digit value is >= 10 add 55 and convert to char, to make it a letter.
4Se[}%N}%          e# Pad each number with spaces to length 4. Put a newline after each row.
\$\endgroup\$
3
\$\begingroup\$

Perl 6, 60 bytes -20% = 48 bytes

{.put for (1..$_ X*1..$_)».base($_)».fmt('%3s').rotor($_)} # 60-20% = 48
#          ^-----------^ produce a list of two cross multiplied lists
#                        ^--------^ convert each to base N
#          format each to 3 spaces ^----------^
#         split the list into N element chunks ^--------^
#^-------^ print each of those on their own line with spaces between elements

( This is almost exactly how I would write it even if I wasn't trying to get it as short as I could )

Usage:

{...}(2)
  1  10
 10 100
my &code = {...}
code 2;
  1  10
 10 100
{...}(12);
  1   2   3   4   5   6   7   8   9   A   B  10
  2   4   6   8   A  10  12  14  16  18  1A  20
  3   6   9  10  13  16  19  20  23  26  29  30
  4   8  10  14  18  20  24  28  30  34  38  40
  5   A  13  18  21  26  2B  34  39  42  47  50
  6  10  16  20  26  30  36  40  46  50  56  60
  7  12  19  24  2B  36  41  48  53  5A  65  70
  8  14  20  28  34  40  48  54  60  68  74  80
  9  16  23  30  39  46  53  60  69  76  83  90
  A  18  26  34  42  50  5A  68  76  84  92  A0
  B  1A  29  38  47  56  65  74  83  92  A1  B0
 10  20  30  40  50  60  70  80  90  A0  B0 100
{...}(18);
  1   2   3   4   5   6   7   8   9   A   B   C   D   E   F   G   H  10
  2   4   6   8   A   C   E   G  10  12  14  16  18  1A  1C  1E  1G  20
  3   6   9   C   F  10  13  16  19  1C  1F  20  23  26  29  2C  2F  30
  4   8   C   G  12  16  1A  1E  20  24  28  2C  2G  32  36  3A  3E  40
  5   A   F  12  17  1C  1H  24  29  2E  31  36  3B  3G  43  48  4D  50
  6   C  10  16  1C  20  26  2C  30  36  3C  40  46  4C  50  56  5C  60
  7   E  13  1A  1H  26  2D  32  39  3G  45  4C  51  58  5F  64  6B  70
  8   G  16  1E  24  2C  32  3A  40  48  4G  56  5E  64  6C  72  7A  80
  9  10  19  20  29  30  39  40  49  50  59  60  69  70  79  80  89  90
  A  12  1C  24  2E  36  3G  48  50  5A  62  6C  74  7E  86  8G  98  A0
  B  14  1F  28  31  3C  45  4G  59  62  6D  76  7H  8A  93  9E  A7  B0
  C  16  20  2C  36  40  4C  56  60  6C  76  80  8C  96  A0  AC  B6  C0
  D  18  23  2G  3B  46  51  5E  69  74  7H  8C  97  A2  AF  BA  C5  D0
  E  1A  26  32  3G  4C  58  64  70  7E  8A  96  A2  AG  BC  C8  D4  E0
  F  1C  29  36  43  50  5F  6C  79  86  93  A0  AF  BC  C9  D6  E3  F0
  G  1E  2C  3A  48  56  64  72  80  8G  9E  AC  BA  C8  D6  E4  F2  G0
  H  1G  2F  3E  4D  5C  6B  7A  89  98  A7  B6  C5  D4  E3  F2  G1  H0
 10  20  30  40  50  60  70  80  90  A0  B0  C0  D0  E0  F0  G0  H0 100
\$\endgroup\$
3
  • \$\begingroup\$ Not an expert, but is the space between 'for' and '(' required? Gotta clip the spaces where possible. \$\endgroup\$
    – JFBM
    Commented Dec 20, 2015 at 20:37
  • \$\begingroup\$ @J_F_B_M I always try removing spaces first. So if there is a space it is required. If I did remove the space it for sure wouldn't even compile as it would treat for( as the beginning of calling a subroutine named for instead of the modifier for loop construct. Which would cause a compilation error. \$\endgroup\$ Commented Dec 20, 2015 at 23:03
  • \$\begingroup\$ Learned something. Thank you. \$\endgroup\$
    – JFBM
    Commented Dec 20, 2015 at 23:19
3
\$\begingroup\$

JavaScript (ES6) 84 (105-20%)

The obvious way, to begin with.

n=>{for(o=i=``;i++<n;o+=`
`)for(j=0;j++<n;)o+=(`   `+(i*j).toString(n)).slice(-4).toUpperCase();alert(o)}

Notes

  • It's a pity js toString produce lowercase letters
  • alert is not the best way to output the table, but it's the shorter, as there is an explicit request to "display on screen"
  • Just returning the value would be a couple bytes shorter.

Less golfed

n=>{
  for(o='', i=0; i++<n; o+='\n')
    for(j=0;j++<n;)
       o+=('   '+(i*j).toString(n)).slice(-4).toUpperCase()
  alert(o)
}
\$\endgroup\$
3
\$\begingroup\$

Python 3, 126 - 20% = 100.8 bytes

The outer function, t, is the one that actually prints the multiplication table. The inner function, i, does the conversion of a number to a base from 2 to 36.

def t(b):
 i=lambda n:(n>=b and i(n//b)or'')+chr(n%b+[48,55][n%b>9]);R=range(b)
 for r in R:print(*('%3s'%i(~r*~c)for c in R))

Hat tip to Boomerang for their solution, and for a golfing tip. I avoided copying anything from Boomerang's solution, but I did allow myself glances at it to see where I could trim more out. And even before that, I found that the more I golfed it, the more mine started to look like Boomerang's!

\$\endgroup\$
6
  • \$\begingroup\$ Nice solution! :) And you get a better score than me! I like the >9 instead of my <10. I'm not too familiar with python3 and starred expressions (I had to look that up). I love your ~ trick, I need to start using that! \$\endgroup\$ Commented Dec 21, 2015 at 10:45
  • \$\begingroup\$ I tested your solution a bit and it looks like i doesn't return more than two base n digits. For example if you do print(i(15,12),i(120,12),i(144,12),i(150,12)) your code returns 13 A0 00 06 instead of 13 A0 100 106. Unfortunately the task requires to print one 3 digit base n number (100). It shouldn't be too difficult to fix but it might add a few bytes... \$\endgroup\$ Commented Dec 21, 2015 at 11:02
  • \$\begingroup\$ @Boomerang: <scratches head> I think I must've broken something, then... because it was working before! The issue appears to be that it won't give a leading 1... oh, wait, I know what the problem is. It should be n>=b, not n>b. \$\endgroup\$ Commented Dec 21, 2015 at 11:40
  • \$\begingroup\$ I found another trick to make the code smaller: define i within t(b) so you can remove the second argument in i! Like this: def t(b): i=lambda n:(n>=b and i(n//b)or'')+chr(n%b+[48,55][n%b>9]) R=range(b) for r in R:print(*('%3s'%i(~r*~c)for c in R)) I'd like to do that in my solution but now both our solutions are pretty close, might as well improve the better one ^^ \$\endgroup\$ Commented Dec 21, 2015 at 11:53
  • \$\begingroup\$ @Boomerang: Hey, yours was first, and I think Python 2 offers enough shortcuts that you could still overtake me. But thanks for the help! \$\endgroup\$ Commented Dec 21, 2015 at 11:59
3
\$\begingroup\$

Javascript (ES6) 96.8 93.6 Bytes (20% of 117)

n=>{b='';for(i=0;i++<n;b+=`\n`)for(j=0;j++<n;)a=(i*j).toString(n).toUpperCase(),b+=' '.repeat(4-a.length)+a;alert(b)}

Explanation

n=>
    {                                     
      b='';                                    //clear table var at each run
      for(i=0;i++<n;b+=`\n`)                   //iterate through rows
        for(j=0;j++<n;)                        //iterate through cols
          a=(i*j).toString(n).toUpperCase(),   //get desired number
          b+=' '.repeat(4-a.length)+a";        //pad to right
    alert(b)                                   //display result
}

-saved 4 bytes thanks to @edc65

\$\endgroup\$
3
  • 1
    \$\begingroup\$ Simply using {} and alert(b) with no eval is shorter. And at least, avoid variable a, it's useless b+=' '.repeat(4-a.length)+(i*j).toString(n).toUpperCase() \$\endgroup\$
    – edc65
    Commented Dec 21, 2015 at 9:47
  • \$\begingroup\$ Thanks 😊 I didn't see the need to display it so for me eval() was originally shorter than returning the value. @edc65 however, if I avoid a how do you then compute ...repeat(4-a.length)...? \$\endgroup\$ Commented Dec 22, 2015 at 5:57
  • \$\begingroup\$ Ugh sorry you're right about a. +1 as is \$\endgroup\$
    – edc65
    Commented Dec 22, 2015 at 7:38
2
\$\begingroup\$

MATLAB, 111*0.8=88.8 110*0.8=88 bytes

My debut here:

@(N)disp(reshape(strrep(strrep([' ',strjoin(cellstr(dec2base([1:N]'*[1:N],N)))],' 0','  '),' 0','  '),4*N,N)')

Explanation:

[1:N]'*[1:N] make multiplication table in base 10

dec2base([1:N]'*[1:N],N) convert to base 12. The output is char array with leading 0-s

strjoin(cellstr(dec2base(___))) convert to cell and back to char joining strings with space yielding 1x575 string

[' ',strjoin(___)] append space to have 576 elements

strrep(___,' 0',' ') remove one leading zero. We do it twice because we have strings with two leading zeros

reshape(___,4*N,N)' convert 1x576 char array into 48x12 char array

disp(___) display the result without ans =

Output:

 1   2   3   4   5   6   7   8   9   A   B  10
 2   4   6   8   A  10  12  14  16  18  1A  20
 3   6   9  10  13  16  19  20  23  26  29  30
 4   8  10  14  18  20  24  28  30  34  38  40
 5   A  13  18  21  26  2B  34  39  42  47  50
 6  10  16  20  26  30  36  40  46  50  56  60
 7  12  19  24  2B  36  41  48  53  5A  65  70
 8  14  20  28  34  40  48  54  60  68  74  80
 9  16  23  30  39  46  53  60  69  76  83  90
 A  18  26  34  42  50  5A  68  76  84  92  A0
 B  1A  29  38  47  56  65  74  83  92  A1  B0
10  20  30  40  50  60  70  80  90  A0  B0 100 

If we don't count statement N=12;, 5*.8=4 bytes are saved. Also, if ans = output is tolerated, then we can remove disp() saving another 6*0.8=4.8 bytes. Of course, there may be other ways to save bytes :)

\$\endgroup\$
3
  • \$\begingroup\$ In general, ans output is tolerated if the output is a function argument. But in this case the challenge says "output should be printed on screen", so ans is not allowed. Also, N should be taken as an input in the extended challenge. You can solve that using an anonymous function: @(n)disp(reshape(strrep(strrep([' ',strjoin(cellstr(dec2base([1:N]'*[1:N],N)))],' 0',' '),' 0',' '),4*N,N)'), which you would call using ans(12) \$\endgroup\$
    – Luis Mendo
    Commented Dec 21, 2015 at 18:11
  • 1
    \$\begingroup\$ Oh and welcome to the site! :-) \$\endgroup\$
    – Luis Mendo
    Commented Dec 21, 2015 at 18:12
  • \$\begingroup\$ @LuisMendo thanks! I'll edit my answer with @(N) notation \$\endgroup\$
    – brainkz
    Commented Dec 21, 2015 at 18:24
2
\$\begingroup\$

Python 3: 166 161 152 - 20% = 121.6 bytes

I know it's inferior to the existing Python answers but I figured to give it a shot. It's my first time posting on this site…

def t(b):
 r=range(1,b+1);f=lambda x:x and f(x//b)+chr((55,48)[x%b>9]+x%b)or''
 print('\n'.join(''.join(B)for B in(('%4s'%f(i*j)for j in r)for i in r)))
\$\endgroup\$
3
  • \$\begingroup\$ There are 3 closing parenthesis and 2 numeric literals followed by spaces. Those spaces are unnecessary. Otherwise nice first try. BTW, Tips for golfing in Python is a nice reading. \$\endgroup\$
    – manatwork
    Commented Dec 22, 2015 at 15:12
  • \$\begingroup\$ Welcome to PPCG.SE, even if it doesn't beat other Python answer, as long as it is different (not the same algorythm/idea), you can post it :). \$\endgroup\$
    – Katenkyo
    Commented Dec 22, 2015 at 15:17
  • \$\begingroup\$ @manatwork Thanks! I got another 9 bytes off with that. \$\endgroup\$ Commented Dec 22, 2015 at 15:34
2
\$\begingroup\$

APL, 32 31×0.8=24.8 bytes

{¯4↑¨⊃∘(⎕D,⎕A)¨¨⍵⊥⍣¯1¨∘.×⍨1+⍳⍵}

In origin 0. In English:

  • ∘.×⍨1+⍳⍵: multiplication table
  • ⍵⊥⍣¯1¨: express in base ⍵ each element of the multiplication table
  • ⊃∘(⎕D,⎕A)¨¨: convert the table of vector of numbers into a table of vectors of chars
  • ¯4↑¨: right align to length 4 each element of the result

The default APL print routine does the right thing.

      {¯4↑¨(⍵⊥⍣¯1¨∘.×⍨1+⍳⍵)⊃¨¨⊂⊂⎕D,⎕A}13
    1     2     3     4     5     6     7     8     9     A     B     C    10 
    2     4     6     8     A     C    11    13    15    17    19    1B    20 
    3     6     9     C    12    15    18    1B    21    24    27    2A    30 
    4     8     C    13    17    1B    22    26    2A    31    35    39    40 
    5     A    12    17    1C    24    29    31    36    3B    43    48    50 
    6     C    15    1B    24    2A    33    39    42    48    51    57    60 
    7    11    18    22    29    33    3A    44    4B    55    5C    66    70 
    8    13    1B    26    31    39    44    4C    57    62    6A    75    80 
    9    15    21    2A    36    42    4B    57    63    6C    78    84    90 
    A    17    24    31    3B    48    55    62    6C    79    86    93    A0 
    B    19    27    35    43    51    5C    6A    78    86    94    A2    B0 
    C    1B    2A    39    48    57    66    75    84    93    A2    B1    C0 
   10    20    30    40    50    60    70    80    90    A0    B0    C0   100 
\$\endgroup\$
2
  • \$\begingroup\$ –1: {¯4↑¨⊃∘(⎕D,⎕A)¨¨⍵⊥⍣¯1¨∘.×⍨1+⍳⍵} \$\endgroup\$
    – Adám
    Commented Jun 28, 2016 at 15:40
  • \$\begingroup\$ Instead of "chars" you should use "bytes" with a link to meta.codegolf.stackexchange.com/a/9429/43319. \$\endgroup\$
    – Adám
    Commented Jun 28, 2016 at 15:42
2
\$\begingroup\$

Vyxal, 20 \$\times\$ 0.8 = 16 bytes

ɾ:v*$τkdkAJİṅ:fÞGL↳⁋

Try it Online!

This could actually be 9*0.8=7.2 bytes if Vyxal had a gridify builtin and a buitlin to convert to a base as a string (with letters).

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

Ruby, 69 66 characters - 20% = 52.8

->n{(r=1..n).map{|a|puts r.map{|b|"%4s"%(a*b).to_s(n).upcase}*''}}

Sample run:

2.1.5 :001 > ->n{(r=1..n).map{|a|puts r.map{|b|"%4s"%(a*b).to_s(n).upcase}*''}}[4]
   1   2   3  10
   2  10  12  20
   3  12  21  30
  10  20  30 100
\$\endgroup\$
1
\$\begingroup\$

ksh93, 51 * 0.8 == 40.8 bytes

eval echo "'
' {"{1..$1}'..$((++n*$1))..$n%3..$1d}'

This should work up to base 64 (the largest radix supported by ksh). Examples:

 $ n= ksh -s 12 <<\EOF
eval echo "'
' {"{1..$1}'..$((++n*$1))..$n%3..$1d}'
EOF


   1   2   3   4   5   6   7   8   9   a   b  10
   2   4   6   8   a  10  12  14  16  18  1a  20
   3   6   9  10  13  16  19  20  23  26  29  30
   4   8  10  14  18  20  24  28  30  34  38  40
   5   a  13  18  21  26  2b  34  39  42  47  50
   6  10  16  20  26  30  36  40  46  50  56  60
   7  12  19  24  2b  36  41  48  53  5a  65  70
   8  14  20  28  34  40  48  54  60  68  74  80
   9  16  23  30  39  46  53  60  69  76  83  90
   a  18  26  34  42  50  5a  68  76  84  92  a0
   b  1a  29  38  47  56  65  74  83  92  a1  b0
  10  20  30  40  50  60  70  80  90  a0  b0 100

 $ n= ksh -s 22 <<\EOF
eval echo "'
' {"{1..$1}'..$((++n*$1))..$n%3..$1d}'
EOF


   1   2   3   4   5   6   7   8   9   a   b   c   d   e   f   g   h   i   j   k   l  10
   2   4   6   8   a   c   e   g   i   k  10  12  14  16  18  1a  1c  1e  1g  1i  1k  20
   3   6   9   c   f   i   l  12  15  18  1b  1e  1h  1k  21  24  27  2a  2d  2g  2j  30
   4   8   c   g   k  12  16  1a  1e  1i  20  24  28  2c  2g  2k  32  36  3a  3e  3i  40
   5   a   f   k  13  18  1d  1i  21  26  2b  2g  2l  34  39  3e  3j  42  47  4c  4h  50
   6   c   i  12  18  1e  1k  24  2a  2g  30  36  3c  3i  42  48  4e  4k  54  5a  5g  60
   7   e   l  16  1d  1k  25  2c  2j  34  3b  3i  43  4a  4h  52  59  5g  61  68  6f  70
   8   g  12  1a  1i  24  2c  2k  36  3e  40  48  4g  52  5a  5i  64  6c  6k  76  7e  80
   9   i  15  1e  21  2a  2j  36  3f  42  4b  4k  57  5g  63  6c  6l  78  7h  84  8d  90
   a   k  18  1i  26  2g  34  3e  42  4c  50  5a  5k  68  6i  76  7g  84  8e  92  9c  a0
   b  10  1b  20  2b  30  3b  40  4b  50  5b  60  6b  70  7b  80  8b  90  9b  a0  ab  b0
   c  12  1e  24  2g  36  3i  48  4k  5a  60  6c  72  7e  84  8g  96  9i  a8  ak  ba  c0
   d  14  1h  28  2l  3c  43  4g  57  5k  6b  72  7f  86  8j  9a  a1  ae  b5  bi  c9  d0
   e  16  1k  2c  34  3i  4a  52  5g  68  70  7e  86  8k  9c  a4  ai  ba  c2  cg  d8  e0
   f  18  21  2g  39  42  4h  5a  63  6i  7b  84  8j  9c  a5  ak  bd  c6  cl  de  e7  f0
   g  1a  24  2k  3e  48  52  5i  6c  76  80  8g  9a  a4  ak  be  c8  d2  di  ec  f6  g0
   h  1c  27  32  3j  4e  59  64  6l  7g  8b  96  a1  ai  bd  c8  d3  dk  ef  fa  g5  h0
   i  1e  2a  36  42  4k  5g  6c  78  84  90  9i  ae  ba  c6  d2  dk  eg  fc  g8  h4  i0
   j  1g  2d  3a  47  54  61  6k  7h  8e  9b  a8  b5  c2  cl  di  ef  fc  g9  h6  i3  j0
   k  1i  2g  3e  4c  5a  68  76  84  92  a0  ak  bi  cg  de  ec  fa  g8  h6  i4  j2  k0
   l  1k  2j  3i  4h  5g  6f  7e  8d  9c  ab  ba  c9  d8  e7  f6  g5  h4  i3  j2  k1  l0
  10  20  30  40  50  60  70  80  90  a0  b0  c0  d0  e0  f0  g0  h0  i0  j0  k0  l0 100
\$\endgroup\$
0
\$\begingroup\$

Pyke, 14 bytes * 0.8 = 11.2 bytes, noncompetitive

QhD]UA*MbQMl2P

Try it here!

Explanation:

            - autoassign Q = eval_or_not_input()
QhD]        - [Q+1, Q+1]
    U       - nd_range(^)
     A*     - apply(*, ^)
       MbQ  - map(base(Q), ^)
          Ml2 - map(lower, ^)
          P - print_grid(^)

Or 12 bytes without the bonus

13D]UA*Mb12P
\$\endgroup\$
1
  • \$\begingroup\$ The challenge specifies uppercase letters \$\endgroup\$
    – Luis Mendo
    Commented Mar 31, 2016 at 20:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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