It's Spanish Time!

24

3

I have a simple task that should be relatively easy to implement by means of code. Your goal is to write a program that will output the time written in Spanish, given the time in HH:MM format. Many people likely don't know how to do this, so I will elaborate.

Time in Spanish is fairly logical. It usually follows the pattern of "Es la/Son las (hour) y (minutes)." Hours are in a 12-hour format, and "Es la" is only used if the hour is 1 (i.e. one o'clock). The minutes are a different story. If the minute is less than 30, then it is represented as shown above. If the minute is over 30, however, then the hour is rounded up and the minute is subtracted. For example, 7:35 is translated to the equivalent of "8 hours minus 25 minutes." Some more examples will be given below. The list of Spanish numbers that are necessary can be found here. There are accents on some numbers, but these are not necessary.

Note: The source says "uno," but to be grammatically correct it should be "una." This shouldn't affect any answers so far.

Note 2: Also, "cero" is not necessary. If your program outputs "Es la una" or "Son las tres," that is fine with me. Sorry for these rule changes.

Rules

  • Input will be provided through STDIN or the equivalent in your language.
  • No reading from outside libraries.
  • Your code can do anything with invalid input.

Bonuses

  • -10 if your code adds these extra phrases - "y cuarto" for :15, "y media" for :30, and "menos cuarto" for :45 (rounded up).
  • -15 if your code can handle A.M. and P.M., responding with "de la mañana" and "de la tarde," accordingly.
  • -15 if your code can translate the current time if no input is provided.

Scoring

  • This is a code-golf challenge, and it will be scored by bytes, not characters.

Examples

Input: 8:10 Output: Son las ocho y diez.

Input: 6:45 Output: Son las siete menos quince (or cuarto).

Input: 1:29 Output: Es la una y veintinueve.

Input: 12:55 Output: Es la una menos cinco.

Let me know if there is anything to specify here. This is my first question, so it is definitely not perfect.

mdc32

Posted 2014-11-07T01:32:42.987

Reputation: 429

I know cero isn't nessesary, but if it makes my code shorter is it okay if I have it? – Maltysen – 2015-01-27T07:24:28.143

For your information, you can get feedback before you post at the sandbox.

– Stretch Maniac – 2014-11-07T01:39:00.397

I predict a negative score solution. – Sparr – 2014-11-07T01:40:12.280

@StretchManiac I don't know how I never saw this. I've never really been active on PPCG, so I guess I haven't really looked at Meta enough. – mdc32 – 2014-11-07T01:40:20.030

1@Sparr I doubt it. There are probably enough numbers that have to be hardcoded for this to happen - at least 45 characters worth, even accounting for patterns. – mdc32 – 2014-11-07T01:41:22.730

Shouldn't 12:55 be 1:55? – None – 2014-11-07T02:54:10.323

Also, the link you use has uno, and you are using una. – None – 2014-11-07T02:54:40.453

@hosch250 Es la una menos cinco, so it's 12:55. And thanks for pointing that out with the uno/una. I'll edit that now. – mdc32 – 2014-11-07T02:54:46.343

What should the output for 1:00 be? As a South American, I'd say Es la una (en punto).. As a code golfer, I'd say Es a una y cero.. – Dennis – 2014-11-07T03:06:13.420

1@Dennis Hmm... I guess either would be fine. Es la una y cero is pretty repetitive, so I see your point. I didn't specify this, so I guess either one would be fine. Thanks for the feedback. – mdc32 – 2014-11-07T03:18:59.440

How should I input AM/PM? Like HH:MM AM or HH:MMPM? – None – 2014-11-07T03:27:24.673

@hosch250 HH:MM AM, preferably. I know this makes it longer, but it makes more sense. – mdc32 – 2014-11-07T03:28:46.873

I thought this would be it. – None – 2014-11-07T03:35:58.793

My program has to wait for input, shouldn't I output the current time if they input 'now' instead? Otherwise, it will always just output the current time without waiting for input. – None – 2014-11-07T03:37:09.923

Or should it be if they press 'Enter' without a time? – None – 2014-11-07T03:38:52.083

@hosch250 It should output the current time if the function is called without any arguments - so in your case, if they press 'Enter' without any input. – mdc32 – 2014-11-07T03:40:18.920

What is the expected output for 00:00? – Peter Taylor – 2014-11-07T07:39:38.437

What is the range of valid input? h==0? h>12? – edc65 – 2014-11-07T09:30:37.163

And what about the full stop in examples? Is it part of requested output? – edc65 – 2014-11-07T09:36:51.110

What to do about midday / midnight? – Rodolfo Dias – 2014-11-07T10:18:12.823

The universal answer to "What time is it": https://www.youtube.com/watch?v=1dQXhuey51M

– William Barbosa – 2014-11-07T13:45:22.473

1You should add 01:21 as a test case, because at least one answerer was confused by what you said about una vs uno. – Peter Taylor – 2014-11-08T09:23:34.117

3The second bonus is (almost?) never worth it because the phrases "de la", "manana" and "tarde" alone count up to 16 bytes already. – britishtea – 2014-11-08T19:11:27.820

Answers

9

JavaScript (ES6) 308 316

Edit2 bug fix Edit forgot to claim the bonus
As a program with I/O via popup

s='media0uno0dos0tres0cuatro0cinco0seis0siete0ocho0nueve0diez0once0doce0trece0catorce0cuarto0dieci0veint'.split(0),
N=n=>n<16?s[n]:n<20?s[16]+s[n-10]:n>29?s[0]:s[17]+(n>20?'i'+s[n-20]:'e'),
[h,m]=prompt().split(':'),
alert(((h=(10-~h+(m>30))%12)?'Son las '+N(1+h):'Es la una')+(m>30?' menos '+N(60-m):-m?' y '+N(~~m):''))

As a testable function

F=t=>(
  s='media0uno0dos0tres0cuatro0cinco0seis0siete0ocho0nueve0diez0once0doce0trece0catorce0cuarto0dieci0veint'.split(0),
  N=n=>n<16?s[n]:n<20?s[16]+s[n-10]:n>29?s[0]:s[17]+(n>20?'i'+s[n-20]:'e'),
  [h,m]=t.split(':'),
  ((h=(10-~h+(m>30))%12)?'Son las '+N(1+h):'Es la una')+(m>30?' menos '+N(60-m):-m?' y '+N(~~m):'')
)

Test In FireFox/FireBug console

for(i=0;i<13;i++)
{
   console.log(F(i+':'+i)+'. '+F(i+':'+(i+15))+'. '+F(i+':'+(i+30))+'. '+F(i+':'+(i+45)))
}

Output

Son las doce. Son las doce y cuarto. Son las doce y media. Es la una menos cuarto
Es la una y uno. Es la una y dieciseis. Son las dos menos veintinueve. Son las dos menos catorce
Son las dos y dos. Son las dos y diecisiete. Son las tres menos veintiocho. Son las tres menos trece
Son las tres y tres. Son las tres y dieciocho. Son las cuatro menos veintisiete. Son las cuatro menos doce
Son las cuatro y cuatro. Son las cuatro y diecinueve. Son las cinco menos veintiseis. Son las cinco menos once
Son las cinco y cinco. Son las cinco y veinte. Son las seis menos veinticinco. Son las seis menos diez
Son las seis y seis. Son las seis y veintiuno. Son las siete menos veinticuatro. Son las siete menos nueve
Son las siete y siete. Son las siete y veintidos. Son las ocho menos veintitres. Son las ocho menos ocho
Son las ocho y ocho. Son las ocho y veintitres. Son las nueve menos veintidos. Son las nueve menos siete
Son las nueve y nueve. Son las nueve y veinticuatro. Son las diez menos veintiuno. Son las diez menos seis
Son las diez y diez. Son las diez y veinticinco. Son las once menos veinte. Son las once menos cinco
Son las once y once. Son las once y veintiseis. Son las doce menos diecinueve. Son las doce menos cuatro
Son las doce y doce. Son las doce y veintisiete. Es la una menos dieciocho. Es la una menos tres

edc65

Posted 2014-11-07T01:32:42.987

Reputation: 31 086

8

Yes, the least expected language to appear on a golf contest, coded by the world's worst golfer, is back!

Java - 676 bytes (716-10-15-15)

Golfed:

class A{void main(String[]a){java.util.Calendar c=java.util.Calendar.getInstance();int h,m;String s="";h=c.get(c.HOUR);m=c.get(c.MINUTE);String[]e={"doce","una","dos","tres","quatro","cinco","ses","siete","ocho","nueve","diez","once","doce","trece","catorce","quarto","çseís","çsiete","çocho","çnueve","xe","xiuno","xidós","xitrés","xiquatro","xicinco","xiséis","xisiete","xiocho","xinueve","media"};for(int i=0;++i<30;e[i]=e[i].replace("ç","dieci"),e[i]=e[i].replace("x","vient"));s+=(h==1&m<30|h==12&m>30)?"Es la ":"Son las ";s+=(m<=30)?e[h]:(h==12&m>30)?e[1]:e[h+1];s+=(m==0)?" certas":(m<=30)?" y "+e[m]:" menos "+e[60-m];s+=(c.get(c.AM_PM)==0)?" de la mañana.":" de la tarde.";System.out.println(s);}}

Ungolfed:

public class A {

    public static void main(String[] a) {
        java.util.Calendar c = java.util.Calendar.getInstance();
        int h, m;
        String s = "";
        h = c.get(c.HOUR);
        m = c.get(c.MINUTE);
        String[] e = {"doce", "una", "dos", "tres", "quatro", "cinco", "ses", "siete", "ocho", "nueve", "diez", "once", "doce", "trece", "catorce", "quarto", "çseís", "çsiete", "çocho", "çnueve", "xe", "xiuno", "xidós", "xitrés", "xiquatro", "xicinco", "xiséis", "xisiete", "xiocho", "xinueve", "media"};
        for (int i = 0; ++i < 30; e[i] = e[i].replace("ç", "dieci"), e[i] = e[i].replace("x", "vient"));
        s += (h == 1 & m < 30 | h == 12 & m > 30) ? "Es la " : "Son las ";
        s += (m <= 30) ? e[h] : (h == 12 & m > 30) ? e[1] : e[h + 1];
        s += (m == 0) ? " certas" : (m <= 30) ? " y " + e[m] : " menos " + e[60 - m];
        s += (c.get(c.AM_PM) == 0) ? " de la mañana." : " de la tarde.";
        System.out.println(s);
    }
}

Deals with the quarto and media, with the AM/PM and has no input. So I can claim all the bonuses, even though that, if I didn't implement those features, I'd have an even lower score, lol. facepalms

Rodolfo Dias

Posted 2014-11-07T01:32:42.987

Reputation: 3 940

6

Python 3: 294 chars - 10 = 284

h,m=map(int,input().split(':'))
t="y"
d="yunoydosytresycuatroycincoyseisysieteyochoynueveydiezyonceydoceytreceycatorceycuarto".split(t)*2
if m>30:h=h%12+1;m=60-m;t="menos"
print(["Es la una","Son las "+d[h]][h>1],t,[d[m]or"cero",["dieci","veint"+'ei'[m>20],"media"][m//10-1]+d[m%10]][m>15]+".")

This gets the ten-point bonus for using "cuarto" and "media"

We read the hours and minutes as ints. If the minutes are above 30, we move to the next hour, measure minutes away from 60, and change the conjunction to "menos".

The list d has translations of Spanish numbers up to 15. We make d[0] be '' to prevent things like "diecicero". This is done by awkwardly calling split(' ') with an initial space; the regular split would just ignore it. The zero-minute case is handled later.

To get numbers above 15, we combine the tens-digit string with the appropriate one-digit string. 15 and 30 are written as "media" and "cuarto" at no cost.

Python 3 saves one char net over Python 2: -4 for input instead of raw_input, +2 for parens in print, +1 for //.

xnor

Posted 2014-11-07T01:32:42.987

Reputation: 115 687

I'm sad to say that it's more complicated than that. 01:21 should be la una y veintiuno because hours are feminine but minutes are masculine. – Peter Taylor – 2014-11-08T09:22:51.457

@PeterTaylor I see. Is uno/una the only number affected? – xnor – 2014-11-08T09:45:09.543

Yes, although if it went up to numbers in the hundreds there would be others. – Peter Taylor – 2014-11-08T12:29:42.280

@PeterTaylor Fixed, for 5 chars. – xnor – 2014-11-08T16:08:19.387

@edc65 Whoops, I forgot to paste in the actual change of una to uno, should work now. – xnor – 2014-11-08T19:13:04.860

Fixed a bug where 20 was veinti rather than veinte. Up to 286 now. – xnor – 2014-11-08T19:19:47.447

You can save a couple characters by using "y" as a delimiter in d, because it's already saved to a variable. – isaacg – 2014-11-09T00:45:54.597

@isaacg That's really cute, thanks. I edited it in. – xnor – 2014-11-09T05:36:02.833

5

C++: 474 ... 422 411 bytes

This version is redeeming the cuarto/media bonus (-10).

#include<cstdlib>
#include<cstdio>
int main(int u,char**v){char*b[]={"cero","una","dos","tres","cuatro","cinco","seis","siete","ocho","nueve","diez","once","doce","trece","catorce","cuarto","dieci","veinti","media",0,"veinte"};int h=atoi(v[1]),m=atoi(v[1]+2+(v[1][2]>57)),n=m>30,o;h=n?h%12+1:h;m=o=n?60-m:m;if(u=m>15&m!=20)o=m%10;printf("%s %s %s %s%s",h>1?"Son las":"Es la",b[h],n?"menos":"y",u?b[m/10+15]:"",b[o?o:m]);}

My first attempt ever at code golfing! Will try to improve it this weekend.

Ungolfed:

#include<cstdlib>
#include<cstdio>
int main(int u,char**v)
{
char*b[]={"cero","una","dos","tres","cuatro","cinco","seis","siete","ocho","nueve","diez","once","doce","trece","catorce","cuarto","dieci","veinti","media",0,"veinte"};
int h=atoi(v[1]),m=atoi(v[1]+2+(v[1][2]>57)),n=m>30,o;
h=n?h%12+1:h;
m=o=n?60-m:m;
if(u=m>15&m!=20)o=m%10;
printf("%s %s %s %s%s",h>1?"Son las":"Es la",b[h],n?"menos":"y",u?b[m/10+15]:"",b[o?o:m]);
}

BMac

Posted 2014-11-07T01:32:42.987

Reputation: 2 118

1Couldn't you m%=10 – Timtech – 2014-11-07T12:20:50.990

Good point! Unfortunately in my new revision I have to assign that value to a different variable, so I can't. – BMac – 2014-11-07T16:47:22.073

Ok, just wondering :) – Timtech – 2014-11-07T22:35:39.507

5

PHP, 351 349 360 - 15 = 345 Bytes

<?$a=split(~ß,~œšßŠ‘ß›Œß‹šŒßœŠž‹ßœ–‘œßŒš–ŒßŒ–š‹šßœ—ß‘Šš‰šß›–š…ß‘œšß›œšß‹šœšßœž‹œšßŽŠ–‘œšß›–šœ–߉š–‘‹–ß‹š–‘‹ž)?><?=preg_filter(~Ð×ÑÔÖÅ×ÑÔÖК,'(($h=($1-($k=$2<31))%12+1)>1?~¬‘ß“žŒß:~ºŒß“žß).$a[$h].($k?~߆ß:~ß’š‘Œß).(($m=$k?$2+0:60-$2)<16?$a[$m]:($m<20?$a[16].$a[$m%10]:($m<21?viente:($m<30?$a[17].$a[$m%10]:$a[18])))).~Ñ',$_GET[0]?:date(~·Å–));

This program is not command line: it takes input via $_GET[0]. You may have to disable notices in your php.ini. Now comes with auto time with no input, thanks to Niet the Dark Absol.

Tricks used:

~(...) saves one byte by bitwise inverting a string, as you don't need quote marks as PHP usually assumes all ASCII from 0x80 to 0xFF is a string.

<?=preg_filter(...,...): The <?= is a shortcut for writing <? echo. preg_filter() usually applies replacements on a string using a regex, but we can use the depreciated /e modifier to evaluate the resulting string as PHP code. Hence, instead of having to split the input string into two separate variables, we can use backreferences ($1 and $2) on the matched input string, saving large amounts of bytes.

Tryth

Posted 2014-11-07T01:32:42.987

Reputation: 750

2You can claim the -15 bonus if you use $_GET[0]?:date(~·Å–) to subtract 3 from your score. – Niet the Dark Absol – 2014-11-08T15:32:53.610

Thanks. I have made that and one other minor improvement. – Tryth – 2014-11-09T01:09:56.210

4

Lua, 450 - 10 (cuarto/media) - 15 (manana/tarde) = 425

n={'uno','dos','tres','cuatro','cinco','seis','siete','ocho','nueve','diez','once','doce','trece','catorce','cuarto',[20]='veinte',[30]='media'}for i=1,9 do n[i+10]=n[i+10]or'dieci'..n[i]n[i+20]='veinti'..n[i]end H,M=io.read():match('(%d+):(%d+)')H,M=H+0,M+0 X,Y='tarde',' y 'if H<12 then X='manana'end if M>30 then H,M,Y=H+1,60-M,' menos 'end H=(H-1)%12+1 S=H==1 and'es la una'or'son las '..n[H]if M>0 then S=S..Y..n[M]end S=S..' de la '..X print(S)
  • Dropped 12 bytes by rewriting the generator for 21-29.
  • Dropped 1 more by replacing H>=12 with H<12 and switching the dependent expression around.
  • Dropped 4 more by polluting the global namespace from a function (evil, but in the interest of golfing :).
  • Fixed the regex, I forgot the colon. Doesn't change the byte count, however.
  • Fixed the case of zero minutes, swapped table.concat out for string ops, and added @edc65's suggestion, ultimately adding 22 bytes.
  • I am shamed. Pulling the function body out into the main chunk reduced the length by a whopping 15 bytes.

criptych stands with Monica

Posted 2014-11-07T01:32:42.987

Reputation: 181

Should use 'una' for hours, 'uno' for minutes. So '01:01' should give Es la una y uno – edc65 – 2014-11-08T19:17:41.420

3

Python 3, 409 bytes

d='cero uno dos tres cuatro cinco seis siete ocho nueve diez once doce trece catorce quince dieciseis diecisiete dieciocho diecinueve veinte xuno xdos xtres xcuatro xcinco xseis xsiete xocho xnueve treinta';d=str(d.replace('x','veinti')).split();t=input().split(':');i=int(t[1]);j=int(t[0]);print(["Son las","Es la"][1<(2*j+i/30)%24<=3],[d[[j%12+1,j][i<31]],'una'][j==1],'y'if i<31 else'menos',d[min(i,60-i)])

user10766

Posted 2014-11-07T01:32:42.987

Reputation:

A long list of strings can be shortened like 'string1 string2 string3'.split() – xnor – 2014-11-07T03:13:03.287

@xnor Alright, thanks! – None – 2014-11-07T03:18:06.590

@hosch250 Also, make sure you're following the comments in the original post again. I will likely be making many minor rule changes, and these will probably help you golf. – mdc32 – 2014-11-07T03:20:23.400

@mdc32 Adjusting right now. I had some errors anyway. – None – 2014-11-07T03:22:13.873

2You can shorten d[j]if i<31 else d[(j+1)%12] to d[(j+(i>30))%12]. In general, if your two alternatives has a similar structure, you can often make a simple expression that equals each respective one depending on the Boolean. – xnor – 2014-11-07T09:16:46.130

Golfed 4 bytes, if it conflicts please notify me. – Timtech – 2014-11-07T12:17:40.560

@xnor No I can't. That returns 'cero' for 12, and it should be 'doce'. My way returns 'doce'. I did shorten it somewhat. – None – 2014-11-07T16:17:31.293

@hosch250 Then maybe I'm not understanding the spec. Can cero never be the hour? For 11:45, yours returns Son las cero menos quince. – xnor – 2014-11-07T20:19:35.227

@xnor Ugh! that should be Son las doce menos quince. – None – 2014-11-07T21:43:16.820

@hosch250 Look like you fixed it. It's still shorter though to do [j%12+1,j][i<31]in place of j if i<31 else j%12+1. If general, it's best to avoid the if/else ternary unless you need to short-circuit evaluating the wrong option. – xnor – 2014-11-07T22:24:25.740

Should use 'una' for hours, 'uno' for minutes. So '01:01' should give Es la una y uno – edc65 – 2014-11-08T19:16:31.940

@edc65 Thanks, I changed it. – None – 2014-11-08T22:12:22.723

3

D - 484 bytes

import std.stdio,std.conv,std.string;void main(){auto n="cero una dos tres cuatro cinco seis siete ocho nueve diez once doce trece catorce quince dieciséis diecisiete dieciocho diecinueve e iuno idos itres icuatro icinco iseis isiete iocho inueve treinta".split;auto p=stdin.readln()[0..$-1];int b=to!int(p[0..$-3]),a=to!int(p[$-2..$]);auto c=a;b=a>30?b+1:b;b%=12;a=a>30?60-a:a;writefln("%s %s %s %s", b==1||b==12?"Es la":"Son las",n[b],c>30?"menos":"y",(a/10==2?"vient":"")~n[a]);}

Hackerpilot

Posted 2014-11-07T01:32:42.987

Reputation: 31

Should use 'una' for hours, 'uno' for minutes. So '01:01' should give Es la una y uno – edc65 – 2014-11-08T19:17:11.813

3

Ruby, 313 (338 - 15 - 10)

This solution translates the current time when no input was given and adds the three phrases "y cuarto", "y media" and "menos cuarto".

require'time'
t,x,s=Time,$*[0],%w[cero una dos tres cuatro cinco seis siete ocho nueve diez once doce trece catorce cuarto]
1.upto(9){|i|i>5?s[10+i]="dieci"+s[i]:0;s[20+i]="veinti"+s[i]}
s[20]="veinte"
s<<"media"
c=x ?t.parse(x):t.new
h,m=c.hour%12,c.min
m<31?(a=" y "):(h,m,a=h+1,60-m," menos ")
$><<(h<2?"Es la ":"Son las ")+s[h]+a+s[m]

britishtea

Posted 2014-11-07T01:32:42.987

Reputation: 1 189

Does it work? Tried in ideone, input '01:01', current time 20:09, output: Son las ocho y diecioch – edc65 – 2014-11-08T19:12:04.580

All the test cases passed for me locally. I see something went wrong with copying the numbers, so I'll fix that. – britishtea – 2014-11-08T19:19:25.617

1"seite" should be "siete" and "neuve" should be "nueve" – jmm – 2014-11-10T17:38:42.343

2

Perl - 297 - 10 + 1 = 288 (counting the p flag)

Edit: thanks to @guifa, I can now claim a bonus :)

#!/usr/bin/perl -p
sub n{($_=shift)%10?(once,doce,trece,catorce,cuarto)[$_>9?$_-11:5]||('',dieci,veinti)[$_/10].(0,un.pop,dos,tres,cuatro,cinco,seis,siete,ocho,nueve)[$_%10]:(cero,diez,veinte,media)[$_/10]}/:/;$a=$`%12;$b=$';$c=$b>30?(++$a,$b=60-$b,menos):'y';$_=($a-1?'Son las ':'Es la ').n($a,a)." $c ".n($b,o).'.'

Here is the same code in multiple lines for readability:

sub n {
        ($_ = shift) % 10
            ? (once, doce, trece, catorce, cuarto)[$_ > 9 ? $_ -11 : 5]
                || ('', dieci, veinti)[$_ / 10]
                . (0, un.pop, dos, tres, cuatro, cinco, seis, siete, ocho, nueve)[$_ % 10]
            : (cero, diez, veinte, media)[$_ / 10]
}
/:/;
$a = $` % 12;
$b = $';
$c = $b > 30 ? (++$a, $b = 60 - $b, menos) : 'y';
$_ = ($a - 1 ? 'Son las ' : 'Es la ') . n($a, a) . " $c " . n($b, o) . '.'

core1024

Posted 2014-11-07T01:32:42.987

Reputation: 1 811

Should use 'una' for hours, 'uno' for minutes. So '01:01' - should give Es la una y uno – edc65 – 2014-11-08T19:04:37.750

If you just change "quince" to "cuarto" and "treinta" to "media", you'll nab a -10 bonus. – user0721090601 – 2014-11-09T01:59:33.047

@edc65 I hope It is OK now... – core1024 – 2014-11-10T01:02:54.673

2

Bash 423

(433 - 10 = 423, removing diacritics and cuarto we could go down to 381)

IFS=: read h m
s=y
m=${m#0}
[ $m -gt 30 ]&&h=$(($h+1))&&s=menos
[ -z ${m%0} ]&&s=en&&m=punto
n[0]=0
o[0]=0
S=" séis siete ocho nueve"
n=(punto una dos trés cuatro cinco $S diez {on,do,tre,cator,quin}ce ${S// / dieci} veinte)
n=($(eval echo "${n[@]}" veinti\$\{n[{1..9}]\}))
n[3]=tres;n[6]=seis
n=(${n[@]} media\  $(tac -s' '<<<${n[@]}))
o=("${n[@]/q*/cuarto}")
a=Son\ las
[ $h = 1 ]&&a=Es\ la
echo $a ${n[$h]/p*/cero} $s ${o[$m]/%a/o}

Ángel

Posted 2014-11-07T01:32:42.987

Reputation: 286

It already uses 'una' for hours and 'uno' for minutes. Look more carefully :) – Ángel – 2014-11-11T09:39:55.033

Sorry, it's not clear at a glance and bash is difficult to test in windows. +1 then. – edc65 – 2014-11-11T16:12:48.403

@edc66, the ordinals are in femenine, then ${o[$m]/%a/o} replaces the trailing a with o for the minutes. – Ángel – 2014-11-12T20:29:41.023

0

Scala 652 bytes - 25

import java.util.Scanner
object S extends App{val s=new Scanner(System.in).useDelimiter("[:\n]")
var h=s.nextInt
var m=s.nextInt
if(m>30)m-=60 else h-=1
val n=m.abs
h%=24
val p=h%12
val l=List("una","dos","tres","cuatro","cinco","seis","siete","ocho","nueve","diez","once","doce","trece","catorce","cuarto")
val k=List("úno","dós","trés",l(3),l(4),"séis",l(6),"ócho",l(8))
println(s"""${if(p==0)"Es la"else"Son las"} ${l(p)} ${if(m>0)"y "else if(m<0)"menos "}${if(n==1)"uno"else if(n==0)""else if(n<=15)l(n-1) else if(n==30)"media"else if(n<20)"dieci"+k(n-11)else if(n==20)"veinte"else"veinti"+k(n-21)} de la ${if(h<12)"mañana"else"tarde"}.""")}

bb94

Posted 2014-11-07T01:32:42.987

Reputation: 1 831

0

Pyth: 277 a bunch more 234 - 10 (cuarto/media bonus) = 224 bytes

Now reduced over 50 bytes from original!

=H" y "ANkmsdcz\:Kc"cero uno dos tres cuatro cinco seis siete ocho nueve diez once doce trece catorce cuarto veinte"dI>k30=k-60k=H" menos "=N?1qN12+N1)++?+"Son las "@KN>N1"Es la una"H??eKqk20?@Kk<k16+?"dieci"<k21+PeK\i@K%kT<k30"media"

Insanely long for Pyth but that's because there's some raw data. Can probably be golfed even further. Uses obvious technique of splitting task up into hours, y/menos, tens digit of minutes, and ones digit of minutes and then translates numbers using translation array and everything else using a crap-ton of ternaries.

=H" y "                 Set H to " y "
A                       Double Assignment
 Nk                     The variables N and k (hours and mins)
 m  cz\:                Map input split by ":"
  sd                    Make both int
Kc"..."d                Set K to string split by spaces
I>k30                   If k>30
     =k-60k             Set k to 60-k
     =H" menos "        Set k to menos instead of y
     =N                 Set N
      ?   qN12          If N=12
       1                Go back to one
       +N1              Increment N
)                       Close entire if block 
+                       Concat of hours and minutes
 +                      Concat hours and y/menos
  ?           >N1       If hour greater than one
   +                    Concat of son las and hour
    "Son las "          "Son las "
    @KN                 Index translation array for hour
   "Es la una"          Else es la una
  H                     " y " or " menos "
 ?               <k30   If minutes less than 30
  ?  qk20               If minutes is 20
   ek                   Last element of array (veinte)
   ?   <k16             Else check if minutes<16
    @Kk                 Get minutes directly from array
    +                   Else tens and ones sum
     ?       <k21       If minutes<21
      "dieci"           "dieci"
      +PeK\i            Else get veinti from veinte
     @K%kT              Ones digit of minutes
  "media"               Else get "media"

Golfing History

  • 10 bytes - bonus, quince and trienta can just be replaced in translation array so no changes required except translation essay and its same size.
  • 6 bytes - reorganized ternaries - unfortunately this removed the 4 consecutive ternary operators :(
  • 6 bytes - other various golfing
  • 6 bytes - golfed initial hour/min assignment
  • +3 bytes - fixed uno/una
  • 3 bytes - constructed veinti from veinte, not hardcoded
  • 18 bytes - extracted dieci from teens<16
  • 2 bytes - removed some spaces in there for no reason
  • 2 bytes - used \ for one char strings

Maltysen

Posted 2014-11-07T01:32:42.987

Reputation: 25 023

For 1 character strings, such as ":" and "i", use \: and \i instead. – isaacg – 2015-01-30T05:36:17.003

@isaacg oh cool I didn't know you could do that, updating – Maltysen – 2015-01-30T14:52:48.663