46
\$\begingroup\$

The French spell out numbers in a peculiar way.

  • 1-16 are "normal"
  • 17-19 are spelled out 10+7. 10+8, 10+9.
  • 20-69 are "normal" (OK, OK! Not really, but they are in this challenge)
  • 70-79 are 60+10, 60+11 ... 60+10+7, 60+10+8, 60+10+9.
  • 80-99 are 4*20, 4*20+1, 4*20+2 ... 4*20+16, 4*20+10+7, 4*20+10+8, 4*20+10+9

Challenge:

Take a positive integer in the range [1,100], and output it the "French way". You must output it exactly as it's shown below, with * and +, so 97 is 4*20+10+7, not [4 20 10 7] or something else.

Test cases:

1  - 1
.. - ..
16 - 16
17 - 10+7
18 - 10+8
19 - 10+9
20 - 20
21 - 21
.. - ..
69 - 69
70 - 60+10
71 - 60+11
72 - 60+12
77 - 60+10+7
78 - 60+10+8
79 - 60+10+9
80 - 4*20
81 - 4*20+1
82 - 4*20+2
.. - ..
90 - 4*20+10
91 - 4*20+11
96 - 4*20+16
97 - 4*20+10+7
98 - 4*20+10+8
99 - 4*20+10+9
100 - 100
\$\endgroup\$
9
  • 15
    \$\begingroup\$ Every language I know has a transition in the "teens", like the one from 16 to 10+7 above. (In English it happens between 12 and 10+3, with a little more morphological disguise.) I've always been a little overobsessed with the fact that different languages make that transition at different numbers. \$\endgroup\$ Apr 26, 2017 at 22:23
  • 25
    \$\begingroup\$ Why should "vingt-deux" be 22 when "dix-huit" is 10+8? \$\endgroup\$
    – Titus
    Apr 27, 2017 at 0:54
  • 11
    \$\begingroup\$ Luckily, this is a programming puzzle site and not a linguistic trivia site. Otherwise people might get annoyed when OP makes silly mistakes. Phew! \$\endgroup\$ Apr 27, 2017 at 8:41
  • 4
    \$\begingroup\$ @StewieGriffin People still got annoyed. \$\endgroup\$
    – Leaky Nun
    Apr 27, 2017 at 8:47
  • 2
    \$\begingroup\$ As a french I do find it quite fine :D. \$\endgroup\$
    – Walfrat
    Apr 27, 2017 at 12:51

12 Answers 12

13
\$\begingroup\$

Excel, 153 149 Bytes

=IF(OR(A1<17,A1>99,AND(A1>19,A1<70)),A1,IF(A1<20,"10+"&A1-10,IF(A1<80,"60","4*20")&IF(A1=80,,IF(MOD(A1,20)>16,"+10+"&MOD(A1,20)-10,"+"&MOD(A1,20)))))

I'm sure this could be better, I struggled to find an efficient way to account for #80.

edit: Consolidated the 'Normal' cases better to save 4 bytes. #80 still sucks.

Can't find a specific answer on here, not sure the rules of code-golf tbh. Can I use multiple cells in Excel, and add the byte count of each?

ie. For an input in cell A1

A2: 11 Bytes

=MOD(A1,20)

A3 (result): 125 Bytes

=IF(OR(A1<17,A1>99,AND(A1>19,A1<70)),A1,IF(A1<20,"10+"&A1-10,IF(A1<80,"60","4*20")&IF(A1=80,,IF(A2>16,"+10+"&A2-10,"+"&A2))))

For a total of 136?

\$\endgroup\$
8
  • \$\begingroup\$ I think it should be allowed to write code in multiple cells. IMHO it's like having intermediate variables or functions in other programming languages. \$\endgroup\$
    – pajonk
    Apr 27, 2017 at 9:19
  • \$\begingroup\$ I feel that there should be some penalty of using multiple cells, just like there's a penalty of using functions in other languages (that of typing the boilerplate to declare the function). Perhaps the tersest supported encoding (ie CSV), so the necessary number of commas and (if required) quotes? \$\endgroup\$
    – Muzer
    Apr 27, 2017 at 9:49
  • \$\begingroup\$ I'm not aware of any format that excel files can be saved in with a recognizable output. CSV files do not by default support functions like these, and will break up any function that uses a comma. If saved as pure text in one column with a new line between cells, it could be copied directly into excel and function. In this case, 1 byte would be added for each additional cell. \$\endgroup\$
    – qoou
    Apr 27, 2017 at 21:57
  • \$\begingroup\$ Save a byte by converting IF(A1=80,,IF(MOD(A1,20)>16,"+10+"&MOD(A1,20)-10,"+"&MOD(A1,20))) to IFS(A1=80,,MOD(A1,20)>16,"+10+"&MOD(A1,20)-10,1,"+"&MOD(A1,20)) \$\endgroup\$
    – Greedo
    Apr 28, 2017 at 10:10
  • \$\begingroup\$ In Libreoffice calc, you can skip the ) at the end, can you do the same in excel? So you can save 5 "bytes" (there are really UCS2-Chars, so if you say Byte == octet, you must count it double). And you must change the , in ; \$\endgroup\$ Apr 28, 2017 at 10:44
8
\$\begingroup\$

Retina, 52 48 bytes

4 bytes saved thanks to Neil

^7\B
60+1
^9\B
81
^8\B
4*20+
1(?=7|8|9)
10+
\+0

Try it online! or verify all inputs (provided by Neil)

Explanation

^7\B
60+1
^9\B
81
^8\B
4*20+

First we handle the translation of 70, 80, and 90. In these first 3 stages, a 7 at the start with another character following it is replaced by 60+1. Similarly, 9 is replaced by 81, and 8 by 4*20+1. The replacement of 9 is essentially changing it to "eighty-ten" and such, so that the 8 is then handled by the next replacement, which saves bytes over writing 4*20+1 twice.

1(?=7|8|9)
10+

This handles the cases of 17, 18, and 19, by replacing the 1 in each with 10+.

\+0

Finally, there should never be a +0 at the end, so delete it if it's there.

\$\endgroup\$
4
  • \$\begingroup\$ Surely instead if look behinds and lookaheads you can use capture groups \$\endgroup\$
    – Downgoat
    Apr 26, 2017 at 21:18
  • \$\begingroup\$ Doesn't work for 7-9, but I don't think you need that lookbehind: Try it online! \$\endgroup\$
    – Neil
    Apr 26, 2017 at 21:26
  • \$\begingroup\$ @Neil I realized that while I was gone :P But thanks for the new version! \$\endgroup\$ Apr 26, 2017 at 22:15
  • \$\begingroup\$ @Downgoat I could replace the lookahead with a capturing group but it wouldn't save any bytes since $1 is just as long as ?=. \$\endgroup\$ Apr 26, 2017 at 22:18
8
\$\begingroup\$

Python 2, 98 bytes

f=lambda x:[`x`*(x%100<70),'10+'+`x-10`][16<x<20]or['60+'+f(x-60),'4*20'+x/81*('+'+f(x-80))][x/80]

Try it online!

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

JavaScript (ES6), 73 71 bytes

f=n=>n>16&n<20?'10+'+n%10:n<70|n>99?n:n%20?f(n-n%20)+'+'+f(n%20):'4*20'

Bonus version that prints the numbers as they are actually spelled for an extra 2 bytes:

f=n=>n<17|n>99?n:n<20?'10+'+n%10:n%20?f(n-n%20)+'+'+f(n%20):n-80?n:'4*20'
\$\endgroup\$
5
  • 1
    \$\begingroup\$ fails for a lot of inputs; actually it only works for 1..20, 30, 40, 50, 60, 80 and 100. \$\endgroup\$
    – Titus
    Apr 27, 2017 at 0:00
  • \$\begingroup\$ @Titus I think you're misunderstanding most of the outputs. 23, for instance, is supposed to output 23, not 20+3. \$\endgroup\$ Apr 27, 2017 at 0:37
  • \$\begingroup\$ Save two bytes with (m=n%20) \$\endgroup\$
    – Titus
    Apr 27, 2017 at 2:53
  • \$\begingroup\$ @Titus Thanks, but I already tried that, and it doesn't work on 70-99 because m gets reset to 0 in the f(n-n%20) call. (It's a global variable) \$\endgroup\$ Apr 27, 2017 at 11:05
  • \$\begingroup\$ You can save a byte by changing n<70|n>99 to n%100<70. Also, could you add a test-compiler? \$\endgroup\$ May 2, 2017 at 10:03
5
\$\begingroup\$

R, 110 bytes

i=scan()
r=i%%10;paste0(ifelse(i>16&i<20,"10+",ifelse(i>69&i<80,"60+10+",ifelse(i>16&i<20,"4*20+",i-r/10))),r)
\$\endgroup\$
1
  • \$\begingroup\$ Try (i-r)/10 instead of floor(i/10). And i>15 should be i>16. \$\endgroup\$
    – Titus
    Apr 26, 2017 at 22:51
5
\$\begingroup\$

PHP, 99 bytes (I wanna be happy version)

a straight port of ETHproductions´ JS, 4 bytes golfed. Prints the numbers as asked for by the OP.

function f($n){return$n<17|$n>19?$n>60&$n<100?($m=$n%20)?f($n-$m)."+".f($m):'4*20':$n:"10+".$n%10;}

breakdown

function f($n){return
    $n<17|$n>19
        ?$n>69&$n<100
            ?($m=$n%20)
                ?f($n-$m)."+".f($m) # 70..79, 81..99
                :'4*20'             # 80
            :$n                     # 1..16, 20..69
        :"10+".$n%10                # 17..19
    ;
}

I wanna be right version, 114 98 bytes

new approach inspired by ETHproductions, prints the numbers as they are actually spelled out.

function f($n){return$n>16&$n<100?$n-80?($m=$n%($n>60?20:10))?f($n-$m)."+".f($m):$n-$m:'4*20':$n;}

try it online.

breakdown

function f($n){return
    $n>16&$n<100
        ?$n-80
            ?($m=$n%($n>60?20:10))
                ?f($n-$m)."+".f($m) # $n%$m>0
                :$n-$m              # 10,20,30,40,50,60
            :'4*20'                 # 80
        :$n                         # 1..16, 100
;}
\$\endgroup\$
0
4
\$\begingroup\$

Python 2, 130 108 bytes

22 bytes saved thanks to @mathjunkie

f=lambda x:79<x<100and('4*20'+('+'+f(x-80))*(x>80))or 69<x<100and'60+'+f(x-60)or 16<x<20and'10+'+`x-10`or`x`

Try it online!

\$\endgroup\$
3
  • \$\begingroup\$ 108 bytes: TIO \$\endgroup\$ Apr 27, 2017 at 1:42
  • 1
    \$\begingroup\$ You need to count f= because you used it inside the lambda. \$\endgroup\$
    – Leaky Nun
    Apr 27, 2017 at 2:35
  • \$\begingroup\$ @LeakyNun fixed \$\endgroup\$
    – Uriel
    Apr 27, 2017 at 15:13
3
\$\begingroup\$

Batch, 220 217 bytes

@set/pn=
@set s=
@if %n% gtr 99 goto g
@if %n% gtr 79 set s=+4*20&set/an-=80
@if %n% gtr 69 set s=+60&set/an-=60
@if %n% gtr 16 if %n% lss 20 set s=%s%+10&set/an-=10
:g
@if %n% gtr 0 set s=%s%+%n%
@echo %s:~1%

Takes input on STDIN. Generating and removing the leading + saves 1 byte over special-casing 80. Edit: Saved 3 bytes thanks to @ConorO'Brien.

\$\endgroup\$
2
  • \$\begingroup\$ You can save 3 bytes by removing @echo off and prefixing all statements except for hte loop statement with @ \$\endgroup\$ May 2, 2017 at 18:21
  • \$\begingroup\$ @ConorO'Brien Huh, I wonder why I forgot to do that this time... \$\endgroup\$
    – Neil
    May 2, 2017 at 18:26
2
\$\begingroup\$

Jelly, 55 bytes

⁹
’,ṃ60Ṁ€
⁹%80“4*20”,
Dj⁾0+µ¹e?“×ØŒ‘
%ȷ2:“FP‘S‘ŀḟ0Ç€j”+

Try it online! or see a test suite

No doubt there is a shorter way!

How?

+ - Link 1, helper for 1-69&100: number s=0, number n
⁹ - link's right argument, n

’,ṃ60Ṁ€ - Link 2, helper for 70-79: number s=1, number n
’       - decrement s -> 0
 ,      - pair -> [0,n]
  ṃ60   - base decompress (vectorises) using [1,2,...60]  effectively -> [60,[1,n%60]]
     Ṁ€ - maximum for €ach effectively -> [60,n%60]

⁹%80“4*20”, - Link 3, helper for 80-99: number s=2, number n
⁹           - link's right argument, n
 %80        - mod 80
    “4*20”  - literal ['4','*','2','0']
          , - pair -> [['4','*','2','0'],n]

Dj⁾0+µ¹e?“×ØŒ‘ - Link 4, reformat 17-19: element v (may be char list or number)
        ?      - if
       e       - v exists in
         “×ØŒ‘ - literal [17,18,19]
               - then:
D              -   convert to decimal list  e.g. [1,7]
  ⁾0+          -   literal ['0','+']
 j             -   join                          [1,'0','+',7]
     µ         - else:
      ¹        -   identity, v

%ȷ2:“FP‘S‘ŀḟ0Ç€j”+ - Main link: number n in [1,100]
 ȷ2                - literal 100
%                  - mod (convert 100 to 0)
    “FP‘           - literal [70,80]
   :               - integer division (vectorises)
        S          - sum (0 for 1-69&100; 1 for 70-79; 2 for 80-99)
         ‘         - increment (...1, 2 or 3)
          ŀ        - call link at index (1, 2 or 3) as a dyad(sum, n)
           ḟ0      - filter out zeros (remove 0 from 4*20+0)
             ǀ    - call the last link (4) as a monad for each
                ”+ - literal '+'
               j   - join
\$\endgroup\$
2
\$\begingroup\$

Pyth, 61 56 bytes

L?}b}17 19++T\+eb|bk?}/QTr6T.s+?<Q80"60+""4*20+"y%Q20\+y

Test it online!

Thanks to Leaky Nun for a 5 byte improvement!

Explanation:

                     | Implicit: Q=eval(input())
L                    | Define y(b):
 ?}b}17 19           |  If b is in the inclusive range from 17 to 19:
          ++T\+eb    |   Return "10+" + (last digit of b)
                 |b  |  Else: if b!=0: return b
                   k |   Else: return an empty string (Leaves a trailing '+' for case 80)
_____________________|________________
?}/QTr6T                              | If 70<=Q<100:
          +                           |  Concatenate the next two expressions:
           ?<Q80                      |   If Q<80:
                "60+"                 |    Evaluate to "60+"
                     "4*20+"          |    Else: Evaluate to "4*20+"
                            y%Q20     |   y(Q%20)
        .s                       \+   |  Strip off trailing '+', if present (for case 80)
                                   y  | Else: return y(Q)
                                   (Q)| Trailing Q is implicitly added
\$\endgroup\$
4
  • \$\begingroup\$ *-Q100>Q69}/QTr6T \$\endgroup\$
    – Leaky Nun
    Apr 27, 2017 at 2:28
  • \$\begingroup\$ @]b}17 19}b}17 19 \$\endgroup\$
    – Leaky Nun
    Apr 27, 2017 at 2:31
  • \$\begingroup\$ +"10+"ebj\+,Teb \$\endgroup\$
    – Leaky Nun
    Apr 27, 2017 at 2:32
  • \$\begingroup\$ @LeakyNun Thanks for the help with golfing! I've made the changes you've suggested. \$\endgroup\$
    – K Zhang
    Apr 27, 2017 at 21:26
1
\$\begingroup\$

Python3, 127 bytes

m,r=map,range;l=[*r(1,17),*m("10+{}".format,(7,8,9))];f=[0,*l,*r(20,61),*m("60+{}".format,l),"4*20",*m("4*20+{}".format,l),100]

Each array element contains its representation:

for i in range(1,101):
    print(i, f[i])

The code does not actually create a function, just an array -- I don't know if that's allowed. Otherwise, I'd have to make this 139 bytes by adding f=[...].__getitem__.

\$\endgroup\$
2
  • \$\begingroup\$ Welcome to PPCG! I believe there was a discussion on meta about submitting arrays as mappings from integers to objects, but I can't seem to find it at the moment. I'll let you know if I do (and what the outcome of that discussion was). Either way, you won't need f=, because unnamed functions (i.e. expressions that evaluate to the submitted function) are fine unless the name is needed for something like recursion. \$\endgroup\$ Apr 28, 2017 at 11:06
  • \$\begingroup\$ There is no clear consensus, but the marginally top voted answer suggests to allow your solution. \$\endgroup\$ Apr 28, 2017 at 13:41
0
\$\begingroup\$

Java 7, 97 96 109 bytes

String c(int i){return i>16&i<20?"10+"+(i-10):i%100<70?i+"":i<80?"60+"+c(i-60):"4*20"+(i<81?"":"+"+c(i-80));}

+13 bytes for bug-fixing case 80.. :(

Explanation:

String c(int i){      // Method with integer parameter and String return-type
  return i>16&i<20?   //  If 17..19:
    "10+"+(i-10)      //   Return "10+" + `i`-10
   :i%100<70?         //  Else if 1..16; 20..69; 100:
    i+""              //   Return `i`
   :i<80?             //  Else if 70..79:
    "60+"+c(i-60)     //   Return "60+" + recursive-call with `i`-60
   :                  //  Else (80..99):
    "4*20"+           //   Return "4*20" +
     (i<81?           //   If 80:
      ""              //    nothing
     :                //   Else (81..99)
      "+"+c(i-80));   //    recursive-call with `i`-80
}                     // End of method

Test code:

Try it here.

class M{
  static String c(int i){return i>16&i<20?"10+"+(i-10):i%100<70?i+"":i<80?"60+"+c(i-60):"4*20"+(i<81?"":"+"+c(i-80));}

  public static void main(String[] a){
    for (int i = 1; i <= 100; i++) {
      System.out.println(c(i));
    }
  }
}
\$\endgroup\$
0

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.