Napisz funkcję, która zwraca czas przeszły danego czasownika

14

Wyzwanie

Napisz funkcję, która pobiera argument, który jest czasownikiem, i zwraca czas przeszły czasownika. (Załóżmy, że czasownik jest regularny)

Czas przeszły

Uwaga: uważaj y za spółgłoskę ani samogłoskę.

Zwykle samo dodanie edpo zakończeniu czasownika powoduje, że czas przeszły jest czas przeszły.

Np .: jumpjumped, askasked

Istnieją jednak inne zasady.

  • Jeśli ostatnim znakiem danego czasownika jest e, po prostu dodaj d.

    Np .: loveloved, movemoved

  • Jeśli czasownik kończy się spółgłoską + y, zmień yna ii dodaj ed.

    Np .: studystudied, crycried

  • Jeśli jednak czasownik kończy się samogłoską + y, po prostu dodaj ed.

    Np .: playplayed, staystayed

  • Jeśli czasownik kończy się samogłoską i spółgłoską, napisz spółgłoskę jeszcze raz i dodaj ed.

    Np .: stopstopped, planplanned

  • Jeśli jednak czasownik kończy się wieloma samogłoskami + spółgłoską lub pojedynczą samogłoską + wieloma spółgłoskami, po prostu dodaj ed.

    Np .: looklooked, jumpjumped

Jest więcej zasad, ale uważajmy tylko nad nimi. Na przykład zgodnie z powyższą zasadą visitvisitted.

Zwycięzca

Ponieważ jest to kod golfowy, wygrywa najkrótszy kod, który poprawnie zwraca czasy przeszłe.

Przykład (JS, 127)

function f(x){return x.replace(/([^aeiouy])y$/,'$1i').replace(/([^aeiouy][aeiou])([^aeiouy])$/,'$1$2$2').replace(/e$/,'')+'ed'}

JiminP
źródło
To miłe wyzwanie.
FUZxxl,
odwrotny wynikający! ciekawy! Spróbuję spróbować, kiedy wrócę do domu :)
DallaRosa,
Każde rozwiązanie krótsze niż 1800 znaków jest nieprawidłowe (czasowniki nieregularne).
Quandary
@Quandary Dlatego powiedziałem „(Załóżmy, że czasownik jest regularny)”
JiminP
@Quandary: Niezupełnie prawda ... patrz odpowiedź Belizariusza .
Simon

Odpowiedzi:

6

sed, 76 znaków

Czy skrypt sed liczy się jako funkcja tego problemu?

s/\([^aeiou]\)y$/\1i/
s/\([^aeiou][aeiou]\)\([^aeiouy]\)$/\1\2\2/
s/e\?$/ed/
migimaru
źródło
4

Mathematica 43 znaki

f=WordData[#,"InflectedForms","List"][[1]]&

Stosowanie:

f /@ {"call", "try", "use", "wash", "play", "stop", "look"}

{"called", "tried", "used", "washed", "played", "stopped", "looked"}

Również:

f /@ {"buy", "run", "swim"}

{"bought", "ran", "swam"}
Dr Belizariusz
źródło
Nie sądzisz, że wyszukiwanie w słowniku jest trochę oszustwem? :-)
Simon
3
@ Simon Zdecydowanie nie. WordData jest częścią języka :)
Dr Belisarius
3

Groovy - 111 znaków

v={it==~'[aeiou]'};p={s->r=s[0..-2];a=s[-1];b=v s[-2];(a=='e'?r:a=='y'?!b?r+'i':s:v(s[-3])|!b|v(a)?s:s+a)+'ed'}

assert ['jump', 'ask', 'love', 'move', 'study', 'cry', 'play', 'stay', 'stop', 'plan', 'look'].collect { p(it) } == ['jumped', 'asked', 'loved', 'moved', 'studied', 'cried', 'played', 'stayed', 'stopped', 'planned', 'looked']
Armand
źródło
2

Perl 5 (82 znaków):

sub f{$_=pop;$C='[^aeiouy]';s/($C)y$/$1i/;s/($C[aeiou])($C)$/$1$2$2/;s/e?$/ed/;$_}

Jestem pewien, że można to poprawić.

Prakash K
źródło
2

C - 120 119 znaków

W typowym stylu C funkcja f aktualizuje bufor ciągów, zakładając, że osoba wywołująca zarezerwowała wystarczająco dużo miejsca dla maksymalnie trzech dodatkowych znaków. Drugi argument należy podać jako 0. Deklaracja globalnej zmiennej stanu ljest uwzględniona w całkowitej liczbie znaków.

#include <stdio.h>
#include <string.h>

l;void f(b,i)char*b;{*b?f(b+1,i/2+4*!strchr("aeiouy",l=*b)):(i-5?*--b=l=='y'&i/2?'i':l:(*b=l),strcpy(b+=l!='e',"ed"));}

int main()
{
  char b[10000];
  while (gets(b)) {
    f(b,0);
    puts(b);
  }
  return 0;
}

Objaśnienie: Funkcja iteruje rekurencyjnie znaki. Drugi argument ikoduje, które z poprzednich trzech znaków były spółgłoskami w jego dolnych trzech bitach. Na końcu ciągu, jeśli i==5trzy ostatnie znaki były spółgłoską, samogłoską i spółgłoską, a zatem ostatni znak musi zostać zduplikowany. Podobnie, jeśli bit 1 ioznacza, że ​​przedostatni znak był spółgłoską, a ostatnim znakiem jest „y”, wówczas „y” zastępuje się „i”.

Han
źródło
1

Scala 199 273 znaków

def v(c:Char)="aeiouy" contains c
def p(o:String)={val s=o.reverse
if(s(0)=='e')o+"d"else
if(!v(s(1))&& s(0)=='y')o.replaceAll("y$","ied")else
if(!v(s(0))&& v(s(1))&& !v(s(2)))o+s(0)+"ed"else
o+"ed"}

Wezwanie:

val li = List ("move", "cry", "plan", "play", "look")
li map p

Moje pierwsze podejście było znacznie dłuższe, przenosząc kaskadę if-else-kaskadową na listę => do funkcji:

type S=String
def f(l:List[(Boolean,S)]):S=if(l(0)._1)l(0)._2 else f(l.tail)
def v(c:Char)="aeiouy" contains c
def c(o:S)={val s=o.reverse
f(List((s(0)=='e',o+"d"),(!v(s(1))&& s(0)=='y',o.replaceAll("y$","ied")),(!v(s(0))&& v(s(1))&& !v(s(2)),o+s(0)+"ed"),(true,o+"ed")))}

Może to podejście jest interesujące. Degolfed i wyjaśnił:

// just for shortening
type S=String
/* take a list of Booleans and Strings, and return early
   if a Boolean is true. This approach would work, 
   if there where much more conditions, I guess.
*/
def doFirst (list: List[(Boolean, S)]): S =
  if (list(0)._1) list(0)._2 else doFirst (list.tail)
// vocal - is it a vocal
def v(c:Char)="aeiouy" contains c
// here is the key function
def toPast(o:S)={
  // reversing the String allows easy access to the last elements, 
  // without considering how long the string is.
  val s=o.reverse
  doFirst (List (
    (s(0)=='e', o+"d"),
    (!v(s(1)) && s(0)=='y', o.replaceAll("y$","ied")),
    (!v(s(0)) && v(s(1)) && !v(s(2)), o+s(0)+"ed"),
    (true, o+"ed")
  ))}
nieznany użytkownik
źródło
0

Ruby, 101 znaków

Prawdopodobnie może być mniejszy.

def f x;x.sub(/([^aeiouy])y$/,'\1i').sub(/([^aeiouy][aeiou])([^aeiouy])$/,'\1\2\2').sub(/e$/,'')+'ed';end

Stosowanie:

f("try")  #=> "tried"
f"call"   #=> "called"
LBg
źródło
Użyj składni lambda Ruby 1.9, f=->(x){...}aby uzyskać krótszy kod. Również aeiouyIMHO powinno być stałe.
Hauleth
0

Kupa - 72 znaki

f[s]s^6pow>4<<last&8*(/"ed""id""eid"/|out|flush)+rep'y'1-2-3"aeiou"ord#s
Thomas Eding
źródło
0

Python - 147

def f (v): T, x, m = „aeiou”, „ed”, v [-1]; return [[[v + x, v + m + x] [v [-2] w T im oraz v [-3] nie w T], [v + x, v [: - 1] + „ied”] [v [-2] nie w T]] [m == 'y'], v + "d "] [m == 'e']  
Kodowanie człowieka
źródło