| Bytes | Lang | Time | Link |
|---|---|---|---|
| 222 | Setanta | 200826T112706Z | bb94 |
| 151 | Python 2 | 200825T102651Z | Sisyphus |
| 139 | JavaScript ES6 | 200825T105013Z | Arnauld |
| 059 | 05AB1E | 200825T131829Z | Kevin Cr |
Setanta, 243 236 235 234 226 222 bytes
gniomh(n){gniomh S(n,c){gniomh Q(t){toradh t|0&1}toradh(n&[13,1,2,3,5,4,4,2,2,2][n%10]+[0,2,6,3][n%10&c%4]+3*Q((c==4|c==8)&n%10000)-13*(Q(!(n%10|c%4))+Q(n%100==0&c%4<3))-Q(n==1&c%4==1)+S(n//10,c+1))|13*Q(!c)}toradh S(n,0)}
Notes:
- This is a port of the Python 2 solution.
- The correct keywords for 'function' and 'if' are
gníomhandmá, respectively, but Setanta allows spelling them without the accents so I did that to save some bytes. - I had to define the
Qfunction above because Setanta doesn't coerce booleans to integers. As far as I know, there's nothing equivalent to ternary expressions in this language. - There are no bitwise operations as far as I know, so I had to stick to array lookups.
Python 2, 163 162 155 151 bytes
-1 thanks to Arnauld, -7 thanks to ovs
Hexdump:
00000000: efbb bf65 7865 6322 789c 1dcb c10e c220 ...exec"x......
00000010: 0cc6 f157 e1c2 d2c2 88b4 6359 34c2 bb20 ...W......cY4..
00000020: b893 7689 274f 3ebb 65a7 36bf 7cff 3dbf ..v.'O>.e.6.|.=.
00000030: eafb d1ab 91b9 e578 1353 a543 fc32 734a .......x.S.C.2sJ
00000040: ebc2 d44b 114b d1a5 8956 f430 7e5d 9866 ...K.K...V.0~].f
00000050: 93bb 5a62 bba1 5fdc e067 1ace 1b97 d226 ..Zb.._..g.....&
00000060: c240 ca40 67ec 75ad 2de8 b92f 7852 440c .@.@g.u.-../xRD.
00000070: 2039 0f62 f43b c885 e21c 7e5c 728f 8fd1 9.b.;....~\r...
00000080: 343a d7fe d154 254b 222e 6465 636f 6465 4:...T%K".decode
00000090: 2827 7a69 7027 29 ('zip')
Unpacked:
f=lambda n,c=0:n and(0x222445321d>>n%10*4&15)+(n%10and c%4*9%12%7)+3*(n%1e4and 272>>c&1)-13*((1>n%10+c%4)+((c%4<3)>n%100))-(n==c%4<2)+f(n/10,-~c)or 13*0**c
Commented version
f=lambda n,c=0:n and # If n is not zero, sum the following:
# The strokes of the current digit
(0x222445321d>>n%10*4&15) # [13,1,2,3,5,4,4,2,2,2][n%10]
# The 10/100/1000 marker stroke count, if
# the currrent digit is zero
+ (n%10and c%4*9%12%7) # [0, 2, 6, 3][n%10 and c%4]
# The 10^4 / 10^8 marker stroke count
+ 3*(n%1e4and 272>>c&1) # 3*(n%10000 and c in [4,8])
- 13*( # Subtract 13 because we overcounted the zeros if
# It's a trailing zero in a group of four
(1>n%10+c%4) # (n%10 == 0 and c%4 == 0)
# and/or if it's part of a group of zeros
+((c%4<3)>n%100) # (n%100 == 0 and c%4 != 3)
) # Subtract 1 if we lead a group of four with 10
- (n==c%4<2) # (n==1 and c%4==1)
+ f(n/10,-~c) # Recurse on next digit
# Else if n=0, return 13 if we are at the first
or 13*0**c # digit, else 0
We also use the exec"...".decode('zip') to compress our code to save a few bytes.
JavaScript (ES6), 148 145 139 bytes
f=(n,i=0,z=n/1e4|0)=>n?f(z,3)-!(n/10^1)+(g=d=>~~d?n%1e4&&(q=n/d%10,x=296/~~q%5^20>>q&1,x?z=x+=3064/d&7:z*q&&(z=0,13))+g(d/10):i)(1e3):!i*13
Black magic
The number of strokes in the Chinese character for a single decimal digit \$1\le q\le 9\$ can be obtained with:
296 / q % 5 ^ 20 >> q & 1This formula returns \$0\$ for \$q=0\$, which is actually what we want because zeros have to be processed separately anyway.
The number of strokes in the Chinese character for a multiplier \$d\in\{1,10,100,1000\}\$ can be obtained with:
3064 / d & 7
Commented
f = ( // f is a recursive function taking:
n, // n = input
i = 0, // i = number of strokes for either 10^4 or 10^8
// (0 for the first iteration, then 3)
z = n / 1e4 | 0 // z = next 4-digit block, also used as a flag to
) => // tell whether zeros must be inserted
n ? // if n is not equal to 0:
f(z, 3) // do a recursive call with the next 4-digit block
- !(n / 10 ^ 1) // subtract 1 if n is the range [10...19] to account
+ // for a leading '10' where the '1' must be omitted
( g = d => // g is a recursive function taking a divisor d
~~d ? // if d greater than or equal to 1:
n % 1e4 && // abort if the entire block is 0
( // otherwise:
q = n / d % 10, // q = (n / d) mod 10
x = 296 / ~~q % 5 // compute the number of strokes x for this
^ 20 >> q & 1, // decimal digit (i.e. the integer part of q)
x ? // if it's not a zero:
z = // set z to a non-zero value
x += // add to x ...
3064 / d & 7 // ... the number of strokes for d
: // else:
z * q && // if both z and q are non-zero:
(z = 0, 13) // add 13 strokes and set z to 0 so that
) // other contiguous zeros are ignored
+ g(d / 10) // add the result of a recursive call with d / 10
: // else:
i // add i to account for either 10^4 or 10^8
)(1e3) // initial call to g with d = 1000
: // else:
!i * 13 // stop the recursion; add 13 if the input was zero
05AB1E, 60 59 bytes
Rv•мΛ~?•ÁyèyĀiŽAΘÁNè]IR4ô¤¤sg*2Q(sεÔ0Û}©J0¢I_+13*ŽE₃Á®¦ĀOèO
Try it online or verify all test cases.
Explanation:
Here a run-down of what each part of the code accomplishes, which we'll sum with O at the very end to get the result:
- Convert each digit to the amount of strokes used, except for edge case 0:
Rv•мΛ~?•Áyè] - Get the strokes of 10, 100, 1000 per part of four digits if the current digit is not a 0:
RvyĀiŽAΘÁNè] - Subtract 1 in case there is a leading
一十→十conversion, by separating the number into parts of four digits, and checking if the first part starts with a1and contains just two digits:IR4ô¤¤sg*2Q( - Add 13 for each 0, excluding those that are adjacent to other 0s, or trailing in every part of four digits:
IR4ôεÔ0Û}©J0¢13* - Take care of edge case \$n=0\$:
I_+13* - Get the strokes of the \$10^4\$ and \$10^8\$, excluding parts that consist solely of 0s:
ŽE₃Á®¦ĀOè
R # Reverse the (implicit) input-integer
v # Loop over each of its digits `y`:
•мΛ~?• # Push compressed integer 1235442220
Á # Rotate it once to the right: 0123544222
yè # Index the current digit `y` into 0123544222
yĀi # If `y` is NOT 0:
ŽAΘ # Push compressed integer 2630
Á # Rotate it once to the right: 0263
Nè # Index the loop-index `N` into 0263 (modulair 0-based)
] # Close both the if-statement and loop
IR # Push the reversed input-integer again
4ô # Split it into parts of size 4, where the last part might be smaller
¤ # Push the last part (without popping the list itself)
¤ # Push the last digit (without popping the number itself)
s # Swap so the number is at the top of the stack again
g # Pop and push its length
* # Multiply it to the digit
2Q # Check if length * digit is equal to 2 (1 if truthy; 0 if falsey)
( # Negate that
s # Swap so the list of parts of 4 is at the top of the stack again
ε # Map each part to:
Ô # Connected uniquify each digit (i.e. 0030 becomes 030)
0Û # Remove any leading 0s
}© # After the map: store this list in variable `®` (without popping)
J # Join it together to a single string
0¢ # Count the amount of 0s left in the string
I_ # Check if the input-integer is 0 (1 if 0; 0 otherwise)
+ # Add that to the count of 0s
13* # Multiply it by 13
ŽE₃ # Push compressed integer 3660
Á # Rotate it once to the right: 0366
® # Push the list from variable `®`
¦ # Remove the first item
Ā # Truthify each part ("" becomes 0; everything else becomes 1)
O # Sum this list
è # Index it into the 0366
O # And finally sum all values on the stack
# (after which this sum is output implicitly as result)
See this 05AB1E tip of mine (section How to compress large integers?) to understand why •мΛ~?• is 1235442220; ŽAΘ is 2630; and ŽE₃ is 3660.