Translate numbers to French

45

4

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

Stewie Griffin

Posted 2017-04-26T20:00:13.677

Reputation: 43 471

15Every 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. – Greg Martin – 2017-04-26T22:23:33.323

25Why should "vingt-deux" be 22 when "dix-huit" is 10+8? – Titus – 2017-04-27T00:54:16.200

@GregMartin Intriguing, I agree. Even the Romance languages do it at different numbers, oddly! (Spanish at 16, Italian and French at 17, albeit with different morphologies, and Latin not at all.) – Noldorin – 2017-04-27T01:31:02.793

11Luckily, this is a programming puzzle site and not a linguistic trivia site. Otherwise people might get annoyed when OP makes silly mistakes. Phew! – Stewie Griffin – 2017-04-27T08:41:21.697

4@StewieGriffin People still got annoyed. – Leaky Nun – 2017-04-27T08:47:31.460

And strictly speaking, although not obviously so, 11 is 1+10 (onze < undecim), 12 is 2+10 (douze < duodecim), 13 is 3+10 (treize < tredecim), 14 is 4+10 (quatorze < quattuordecim), 15 is 5+10 (quinze < quindecim), and 16 is 6+10 (seize < sedecim). – Leaky Nun – 2017-04-27T08:50:45.097

2As a french I do find it quite fine :D. – Walfrat – 2017-04-27T12:51:54.570

1As a French speaking Swiss, that disturbs me a bit (for me: soixante-dix = septante, quatre-vingts = huitante, quatre-vingt-dix = nonante). Your challenge would be so much less challenging, though. – SteeveDroz – 2017-05-02T09:21:41.410

A curious fact is the language of love stops at 69! – sergiol – 2017-10-21T01:10:51.880

Answers

13

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?

qoou

Posted 2017-04-26T20:00:13.677

Reputation: 711

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. – pajonk – 2017-04-27T09:19:13.457

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? – Muzer – 2017-04-27T09:49:26.237

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. – qoou – 2017-04-27T21:57:05.387

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)) – Greedo – 2017-04-28T10:10:44.040

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 ; – 12431234123412341234123 – 2017-04-28T10:44:29.570

@12431234123412341234123 No, but you can delete all the trailing parentheses and Excel autocorrects for you. I'm guessing that doesn't count – Greedo – 2017-04-28T10:44:31.117

@Greedo For curiosity, i create a Open document spreadsheet file with LO, have a formula with the closing parentheses in it and save it. After that i edit this file manual and remove the closing parentheses ), LO can open this file again without a problem (and add the missing parentheses automatic). So maybe you can say, you do not count the ) (i don't know, what make more sense), but the formula in the file is longer because of the escaped < and > – 12431234123412341234123 – 2017-04-28T11:07:09.423

@qoou, create a CSV document, first line input, lines 2 & 3 as above, surrounded by ". = 152 bytes. – Wernisch – 2019-11-18T15:23:38.610

8

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.

Business Cat

Posted 2017-04-26T20:00:13.677

Reputation: 8 927

Surely instead if look behinds and lookaheads you can use capture groups – Downgoat – 2017-04-26T21:18:38.067

Doesn't work for 7-9, but I don't think you need that lookbehind: Try it online!

– Neil – 2017-04-26T21:26:18.660

@Neil I realized that while I was gone :P But thanks for the new version! – Business Cat – 2017-04-26T22:15:07.977

@Downgoat I could replace the lookahead with a capturing group but it wouldn't save any bytes since $1 is just as long as ?=. – Business Cat – 2017-04-26T22:18:41.330

7

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'

ETHproductions

Posted 2017-04-26T20:00:13.677

Reputation: 47 880

1fails for a lot of inputs; actually it only works for 1..20, 30, 40, 50, 60, 80 and 100. – Titus – 2017-04-27T00:00:20.727

@Titus I think you're misunderstanding most of the outputs. 23, for instance, is supposed to output 23, not 20+3. – ETHproductions – 2017-04-27T00:37:47.410

Save two bytes with (m=n%20) – Titus – 2017-04-27T02:53:49.203

@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) – ETHproductions – 2017-04-27T11:05:38.060

You can save a byte by changing n<70|n>99 to n%100<70. Also, could you add a test-compiler? – Kevin Cruijssen – 2017-05-02T10:03:10.540

7

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!

xnor

Posted 2017-04-26T20:00:13.677

Reputation: 115 687

5

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)

Neil

Posted 2017-04-26T20:00:13.677

Reputation: 2 417

Try (i-r)/10 instead of floor(i/10). And i>15 should be i>16. – Titus – 2017-04-26T22:51:55.503

5

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
;}

Titus

Posted 2017-04-26T20:00:13.677

Reputation: 13 814

4

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!

Uriel

Posted 2017-04-26T20:00:13.677

Reputation: 11 708

108 bytes: TIO

– math junkie – 2017-04-27T01:42:37.980

1You need to count f= because you used it inside the lambda. – Leaky Nun – 2017-04-27T02:35:50.403

@LeakyNun fixed – Uriel – 2017-04-27T15:13:03.393

3

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.

Neil

Posted 2017-04-26T20:00:13.677

Reputation: 95 035

You can save 3 bytes by removing @echo off and prefixing all statements except for hte loop statement with @ – Conor O'Brien – 2017-05-02T18:21:08.057

@ConorO'Brien Huh, I wonder why I forgot to do that this time... – Neil – 2017-05-02T18:26:54.590

2

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

K Zhang

Posted 2017-04-26T20:00:13.677

Reputation: 5 698

*-Q100>Q69}/QTr6T – Leaky Nun – 2017-04-27T02:28:53.620

@]b}17 19}b}17 19 – Leaky Nun – 2017-04-27T02:31:12.720

+"10+"ebj\+,Teb – Leaky Nun – 2017-04-27T02:32:06.747

@LeakyNun Thanks for the help with golfing! I've made the changes you've suggested. – K Zhang – 2017-04-27T21:26:08.923

2

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

Jonathan Allan

Posted 2017-04-26T20:00:13.677

Reputation: 67 804

1

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__.

emu

Posted 2017-04-26T20:00:13.677

Reputation: 111

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. – Martin Ender – 2017-04-28T11:06:39.537

There is no clear consensus, but the marginally top voted answer suggests to allow your solution.

– Martin Ender – 2017-04-28T13:41:14.087

0

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));
    }
  }
}

Kevin Cruijssen

Posted 2017-04-26T20:00:13.677

Reputation: 67 575