Golf the Chinese 9*9 multiple table

18

3

Output the following table:

一一得一
一二得二 二二得四
一三得三 二三得六 三三得九
一四得四 二四得八 三四十二 四四十六
一五得五 二五一十 三五十五 四五二十 五五二十五
一六得六 二六十二 三六十八 四六二十四 五六三十 六六三十六
一七得七 二七十四 三七二十一 四七二十八 五七三十五 六七四十二 七七四十九
一八得八 二八十六 三八二十四 四八三十二 五八四十 六八四十八 七八五十六 八八六十四
一九得九 二九十八 三九二十七 四九三十六 五九四十五 六九五十四 七九六十三 八九七十二 九九八十一

Or you can use the first three letters in its English word, in case that some languages don't support Chinese characters:

OneOneGetOne
OneTwoGetTwo TwoTwoGetFou
OneThrGetThr TwoThrGetSix ThrThrGetNin
OneFouGetFou TwoFouGetEig ThrFouTenTwo FouFouTenSix
OneFivGetFiv TwoFivOneTen ThrFivTenFiv FouFivTwoTen FivFivTwoTenFiv
OneSixGetSix TwoSixTenTwo ThrSixTenEig FouSixTwoTenFou FivSixThrTen SixSixThrTenSix
OneSevGetSev TwoSevTenFou ThrSevTwoTenOne FouSevTwoTenEig FivSevThrTenFiv SixSevFouTenTwo SevSevFouTenNin
OneEigGetEig TwoEigTenSix ThrEigTwoTenFou FouEigThrTenTwo FivEigFouTen SixEigFouTenEig SevEigFivTenSix EigEigSixTenFou
OneNinGetNin TwoNinTenEig ThrNinTwoTenSev FouNinThrTenSix FivNinFouTenFiv SixNinFivTenFou SevNinSixTenThr EigNinSevTenTwo NinNinEigTenOne

You can output in any reasonable format, e.g. plain text separated with space/comma/tab and newline, 2D array where empty places are empty or don't exist (The 2*1 place is empty so there shouldn't be anything in the array).

Code golf, shortest code in bytes win. GBK encoding is allowed, where each Chinese character use 2 bytes.

Converting Table:

一   One
二   Two
三   Thr
四   Fou
五   Fiv
六   Six
七   Sev
八   Eig
九   Nin
十   Ten
得   Get

l4m2

Posted 2018-03-09T18:21:10.800

Reputation: 5 985

The rest seems fairly intuitive, but could you at least explain how 十 and 得 work? – Dennis – 2018-03-09T18:26:35.137

得 is only used when the product is smaller than 10 – l4m2 – 2018-03-09T18:29:59.893

ahhh, so if it is greater that 10 instead 得 we are supposed to use 十? – Luis felipe De jesus Munoz – 2018-03-09T19:09:08.547

@LuisfelipeDejesusMunoz and [11,19] are special with a bare 十. – FrownyFrog – 2018-03-09T19:43:44.347

我能确认这是正确的。(Translation: I can confirm that this is correct) – Esolanging Fruit – 2018-03-09T19:51:00.103

It seems unfair to require a three-byte Roman string (four if you need a null terminator) in place of a two-byte Chinese character. – David Richerby – 2018-03-10T13:23:30.887

@David Richerby The roman output is a bit more expensive to fairten languages that are optimized for letters – l4m2 – 2018-03-10T14:24:44.137

Seems someone say "二五得十", and that's right but worse than "二五一十". Here "二五一十" is required

– l4m2 – 2018-03-10T16:48:49.997

Why I learned 三五一十五 / 二八一十六 at school. I must attend a fake school. // Anyway, I can't recite it until maybe 4th grade. I just try to do a mental arithmetic adding, when I was asked to recite this.... – tsh – 2018-03-12T02:51:13.070

I say "一五五 二五一十 三五十五 四五二十 五五廿五" all the "x十" is expressed with a single syllable when something followed – l4m2 – 2018-03-12T04:00:30.893

@tsh Same, I learned it that way as well. – ericw31415 – 2018-03-17T19:40:31.380

Answers

8

Stax, 66 characters

9mYF"得一二三四五六七八九"cacy*~@ny@\p;11AH:b!n;A/X@]z?px'十z?p,A%sn@]z?' +qD

Number of bytes depends on the encoding used for Chinese characters.

Run and debug online!

Explanation

9mYF...D    Loop `n` times and print a newline after each loop, `n`=1..9

"..."cay*~@ny@\p
"..."c              Push the string and duplicate it
      ay            Fetch the outer loop variable
        *           Multiply with the inner loop variable
         ~          Move the product to input stack for later use
          @         Take character at the index specified by inner loop variable
           ny@      Take character at the index specified by outer loop variable
              \p    Print the two characters

;11AH:b!n;A/X@]z?p
;11AH:b!        ?p    Is the product not in range [11,20)?
                      Output (*) if true, (**) if false.
        n;A/X@        Character at the index of the "ten" digit of product
              ]       Convert character to string (*)
               z      Empty string (**)

x'十z?p,A%sn@]z?' +q
x'十z?p                Print "十" if the "ten" digit is non-zero, nothing otherwise
       ,A%sn@]z?       Get the character specified by the last digit if that digit is non-zero, empty string otherwise
                ' +q   Append a space and print

Alternative version (Stax 1.0.6), 59 bytes (by @recursive)

This uses a feature that is inspired by this challenge and is only included in Stax 1.0.6 which postdates the challenge.

éz░╖▐5à{│`9[mLùÜ•ëO╞îπl▼Γ─§╥|▒╛Δ◙Φµ'r╠eƒÿQ╫s♪Ω]£ï♪D3╚F◙δÿ%‼

The ASCII version is

9mX{x\_x*YA/]yA-y20<*!*+y9>A*+yA%]0-+"NT|,,t.%,p&()(!'^pq kzi !X6"!s@mJ

This version constructs the index array and then uses it to index the string of Chinese characters to avoid redundant stack operations (c,a,n) and multiple @s.

Explanation

9mX{...m    Loop `n` times and map `1..n` to a list of strings, `n`=1..9
        J   Join the strings with space and print with a newline

x\_x*YA/]yA-y20<*!*+y9>A*+yA%]0-+"..."!s@
x\                                           A pair: (inner loop variable, outer loop variable)
  _x*Y                                       Product of inner and outer loop variable
      A/                                     floor(product/10)
        ]                                    [floor(product/10)]
         yA-                                 Product does not equal 10
            y20<                             Product is less than 20
                *!                           `Nand` of them
                                             This is true (1) if the product is in the range {10}U[20,81]
                  *                          Repeat [floor(product/10)] this many times
                                             This results in itself if the predicate above is true, or empty array if it is false
                   +                         Add it to the list of [inner loop var, outer loop var]
                                             This list will be used to index the string "得一二三四五六七八九十"
                    y9>A*                    Evaluates to 10 if the product is larger than 9, 0 otherwise
                                             When indexed, they become "十" and "得", respectively
                         +                   Append to the list of indices
                          yA%                Product modulo 10
                             ]0-             [Product modulo 10] if that value is not zero, empty array otherwise
                                +            Append to the list of index
                                 "..."!      "得一二三四五六七八九十"
                                       s@    Index with constructed array

Weijun Zhou

Posted 2018-03-09T18:21:10.800

Reputation: 3 396

Stax 1.0.6 can do it in 59, but it postdates the challenge, so it isn't qualified IMO.

– recursive – 2018-03-12T17:49:55.473

Worth mentioning anyway. It also obviously uses some optimization that is also available before 1.0.6. – Weijun Zhou – 2018-03-12T18:00:01.573

1I suspect there's still a decent amount of optimization room left in it, but I'm going to leave it alone for now. – recursive – 2018-03-12T18:11:28.217

@recursive Nowadays, newer programming languages that are not made purposefully for a question do not have to be marked ‘non competing’ (somebody link the meta post) – Stan Strum – 2018-03-13T20:01:21.540

1

@StanStrum Here's the meta post

– PunPun1000 – 2018-03-16T18:19:50.123

5

Python 3, 151 149 146 bytes

-3 bytes thanks to Rod.

l=" 一二三四五六七八九"
for i in range(1,10):print([l[j//i]+l[i]+('得',l[j//10][10<j<20:]+'十')[j>9]+l[j%10]for j in range(i,i*i+1,i)])

Try it online!

ovs

Posted 2018-03-09T18:21:10.800

Reputation: 21 408

Just a small note, you could use zero-width space '\u200b' (+2 bytes) instead space for an exact output

– Rod – 2018-03-09T19:35:08.643

3

Javascript, 190 bytes

(_="得一二三四五六七八九十")=>{for(i=1;i<10;i++){for(t="",v=0;v<i;t+=_[++v]+_[i]+[...(v*i+'')].map((a,b,c) => c.length>1&&b==0?(a>1?_[a]+'十':'十'):b==0?'得'+_[a]:_[a]).join``+' ');console.log(t)}}

a=(_=" 一二三四五六七八九")=>{for(i=1;i<10;i++){for(t="",v=0;v<i;t+=_[++v]+_[i]+[...(v*i+'')].map((a,b,c) => c.length>1&&b==0?(a>1||c[1]==0?_[a]+'十':'十'):b==0?'得'+_[a]:_[a]).join``+' ');console.log(t)}}
a()

Luis felipe De jesus Munoz

Posted 2018-03-09T18:21:10.800

Reputation: 9 639

@l4m2 Yes, i did not notice the difference when using 得 – Luis felipe De jesus Munoz – 2018-03-09T19:27:00.090

1@FrownyFrog when is 10 is 一十 but when is 15 or 16 or any other number we omit ? – Luis felipe De jesus Munoz – 2018-03-09T19:57:58.557

@FrownyFrog Can you take a look now? – Luis felipe De jesus Munoz – 2018-03-09T20:04:36.160

All fine, well done. – FrownyFrog – 2018-03-09T20:09:13.273

Try (_="得一二三四五六七八九十")=>eval("for(i=1;i<10;i++){for(t='',v=0;v<i;t+=_[++v]+_[i]+[...(v*i+'')].map((a,b,c)=>c.length>1&&b==0?(a>1?_[a]+'十':'十'):b==0?'得'+_[a]:_[a]).join\`+' ');t")`. I haven't looked too closely, but there are definitely some other things that you can golf. – Mama Fun Roll – 2018-03-14T03:00:44.573

2

Yabasic, 250 242 238 bytes

A answer with unicode characters?! What?

An anonymous function and declared helper function, c(n) that takes no input and outputs to STDOUT

For r=1To 9
For c=1To r
c(c)
c(r)
If!r*c>9Then?"得";Fi
c(r*c)
?" ";
Next
?
Next
Sub c(n)
s$="一二三四五六七八九"
If n>19Then?Mid$(s$,Int(n/10)*3-2,3);Fi
If n=10Then?"一";Fi
If n>9Then?"十";Fi
?Mid$(s$,Mod(n,10)*3-2,3);
End Sub

Try it online!

Taylor Scott

Posted 2018-03-09T18:21:10.800

Reputation: 6 709

2

Ruby, 166 bytes

->{(1..9).map{|a|(1..a).map{|b|p=a*b;([b,a]+(p<10?[0,p]:p<11?[1,10]:p<20?[10,p%10]:[p/10,10]+(p%10<1?[]:[p%10]))).map{|d|"得一二三四五六七八九十"[d]}*""}}}

Try it online!

A lambda returning a 2D array of strings.

->{
  (1..9).map{|b|                  # b is the multiplier
    (1..b).map{|a|                # a is the multiplicand
      p=a*b;                      # p is the product
      (                           # We will build an array of indexes into a ref string:
        [a,b] + (                 #   The first two indexes will be a and b
        p<10 ? [0,p] :            #   Case 1: abGp (single digit sums)
        p<11 ? [1,10] :           #   Case 2: 251X (only happens once)
        p<20 ? [10,p%10] :        #   Case 3: abXd (12-18, d is the ones digit)
        [p/10,10]+(               #   (Cases 4 and 5 share a prefix)
          p%10<1 ? [] :           #   Case 4: abcX (20, 30, 40, c is the tens digit)
          [p%10]))                #   Case 5: abcXd (two-digit product, p = 10*c+d)
      ).map{|d|
        "得一二三四五六七八九十"[d] # Fetch the character for each index
      }*""                        # Join the characters into words
    }
  }
}

benj2240

Posted 2018-03-09T18:21:10.800

Reputation: 801

1

Python 3, 196 bytes

lambda c=' 一二三四五六七八九':[[c[j]+c[i]+[('得'+c[(i*j%10)]),((c[(int(i*j/10))]*((i*j>19)or(i*j==10)))+'十'+(c[i*j%10])*(i*j%10!=0))][i*j>9]for j in range(1,i+1)]for i in range(1,10)]

Try it online!

Dat

Posted 2018-03-09T18:21:10.800

Reputation: 879

二五一十九 二六一十二 two kinds of wrong – l4m2 – 2018-03-09T19:08:45.423

@FrownyFrog fixed... – Dat – 2018-03-09T20:42:27.407

c[(i*j%10)] => c[i*j%10]? – l4m2 – 2018-03-10T16:23:21.357

1

Retina, 100 characters, 122 bytes


9*
_
$`_$n
_
$%`_$.%= 
(_+)(.)
$.1,$2,$.($.1*$2*)
\B.
:$&
:0
:
1:\b
:
,(. )
,0$1
T`,d:`_得一二三四五六七八九十

Try it online! Explanation:


9*

Insert nine _s.

_
$`_$n

Expand to 9 rows of 1 to 9 _s.

_
$%`_$.%= 

(note trailing space) Expand to 9 rows of 1 to i _s plus i as a digit.

(_+)(.)
$.1,$2,$.($.1*$2*)

Convert the _s to decimal and multiply by i.

\B.
:$&

Insert a : if the answer has two digits. This will become the ten character.

:0
:

Delete zero units.

1:\b
:

Delete the 1 from 1: unless it's 1:0 which had its zero removed.

,(. )
,0$1

Inser a 0 for single-digit answers; this will become the get character.

T`,d:`_得一二三四五六七八九十

Fix up all the characters.

Neil

Posted 2018-03-09T18:21:10.800

Reputation: 95 035

1

JavaScript (Node.js), 141/130 bytes

(s=[...'得一二三四五六七八九'])=>s.map((A,i)=>s.map((B,j)=>i<j|!j?'':B+A+[s[(q=i*j)/10|-(q>11&q<19)]]+(q>9?'十':'')+[s[q%10||s]]))

Try it online!

l4m2

Posted 2018-03-09T18:21:10.800

Reputation: 5 985

Could you please remove the "UTF8" from header? It isn't necessary, but it tricks leaderboard scripts, making them think this answer is only 8 bytes long. – RedClover – 2018-03-20T16:34:38.533

1

APL (Dyalog), 75 100 characters, 97 122 bytes

k t←' 一二三四五六七八九得十'10
∘.{⍺<⍵:''⋄(s=10)∨19<s←⍺×⍵:k[1+⍵⍺(⌊s÷t)11,t|s]⋄9<s:k[1+⍵⍺,11,t|s]⋄k[⍵⍺t s+1]}⍨⍳9

Try it online!

Uriel

Posted 2018-03-09T18:21:10.800

Reputation: 11 708

I'd love to improve it if the downvoter would tell what's wrong with it. – Uriel – 2018-03-21T09:18:34.100

Oh, right, so for 11 to 19 inclusive the output should be 4 characters, with no 一 – FrownyFrog – 2018-03-21T20:25:37.410

@FrownyFrog fixed – Uriel – 2018-03-21T21:10:11.340

0

Python 3, 142 bytes

Structure is similar to ovs's 146 byte answer, but the middle terms work in a different way.

n=" 一二三四五六七八九"
for x in range(1,10):print([n[y//x]+n[x]+n[y//10][20>y!=10:]+'得十'[y>9]+n[y%10]for y in range(x,x*x+1,x)])

Try it online!

Explanation

The most interesting term is the term for the number of tens:

n[y//10][20>y!=10:]

Note that 20>y!=10 means 20 > y and y != 10, which is False when the number of tens should be included and True otherwise.

False has an integer value of 0 and True has an integer value of 1, so whereas n[y//10] is always one character long, the subscript [20>y!=10:] is equivalent to [0:1] (i.e. "the character") when the number of tens should be included and [1:1] (i.e. "no characters") otherwise.

The following term,

'得十'[y>9]

is easier to understand; note that:

  • The output for every result <= 9 should contain
  • The output for every result > 9 should contain
  • can be handled after the 'tens' term because the 'tens' term always evaluates to an empty string when there is a

Note on trailing spaces

The trailing spaces for multiples of ten stretch the specification slightly - as mentioned by rod, this could be made visually perfect by using a zero-width space, but then you would also have to unpack the arrays using print(*[...]) as the zero-width space is represented as a literal "\u200b" when printed in an array.

mjayfrancis

Posted 2018-03-09T18:21:10.800

Reputation: 1

0

JavaScript, 190 bytes

(s="得一二三四五六七八九十",o="")=>eval(`for(i=1;i<10;i++){for(j=1;j<=i;j++){o+=s[j]+s[i]+(i*j<10?s[0]:i*j<11?s[1]+s[10]:i*j<20?s[10]:s[i*j/10|0]+s[10])+(i*j%10?s[i*j%10]:"")+" "}o+="\\n"}`)

I will try to golf this later.

ericw31415

Posted 2018-03-09T18:21:10.800

Reputation: 2 229

0

Ruby, 136 bytes

Byte count in UTF-8, should be 128 bytes with Han characters counted as 2 instead of 3.

1.upto(9){|x|p (1..x).map{|y|[y,x,x*y/10,?X,x*y%10].join.sub(/(?<=0)X|1(?=X[1-9])|0$/,'').tr"0-9X","得一二三四五六七八九十"}}

Try it online!

  1. Construct the strings from multipliers' and products' digits with the latter separated by X as a placeholder for .
  2. Do some regex fun to drop X for products <10, leading ones for "-teen" products, and trailing zeroes.
  3. Translate digits and X to Han characters.

Kirill L.

Posted 2018-03-09T18:21:10.800

Reputation: 6 693

0

///, 301 bytes (GBK*)

/*/\/\///1/一*2/二*3/三*4/四*5/五*6/六*7/七*8/八*9/九*0/十*=/得*I/
1*t/ 2*T/ 3/11=1I2=2t2=4I3=3t3=6T3=9I4=4t4=8T402 4406I5=5t510T505 4520 55205I6=6t602T608 46204 5630 66306I7=7t704T7201 47208 57305 67402 77409I8=8t806T8204 48302 5840 68408 78506 88604I9=9t908T9207 49306 59405 69504 79603 89702 99801

Try it online!

*Spec explicitly allows GBK → Unicode conversion.

Erik the Outgolfer

Posted 2018-03-09T18:21:10.800

Reputation: 38 134

0

Pyth, 49 characters, 71 bytes

J" 一二三四五六七八九"jmj;m+s@LJkr6>3+\得j\十@LJj*FkT,RdSdS9

Uses UTF-8 encoding. Try it online here.

In the following explanation, the ? characters are substitutes for the correct Chinese characters - I'm too lazy to make everything line up properly...

J" ?????????"jmj;m+s@LJkr6>3+\?j\?@LJj*FkT,RdSdS9   
J" ?????????"                                       Assign space + glyphs for 1-9 to J
                                               S9   [1-9]
              m                                     Map each element, as d, using:
                                             Sd       [1-d]
                                          ,Rd         Pair each element of the above with d
                                                        e.g. for d=3, yields [[1,3],[2,3],[3,3]]
                 m                                    Map each element, as k, using:
                                      *Fk               Get the product of the pair
                                     j   T              Get decimal digits of the above (convert to base 10)
                                  @LJ                   Map each digit to its index in J
                               j\?                      Join the above on ? ("Ten")
                            +\?                         Prepend ? ("Get")
                          >3                            Take the last 3 characters of the above
                        r6                              Strip whitespace
                  +                                     Prepend to the above...
                   s@LJk                                Concatenated digits of k in lookup string
               j;                                     Join result on spaces
             j                                      Join result on newlines, implicit print

Sok

Posted 2018-03-09T18:21:10.800

Reputation: 5 592