Verilen fiilin geçmiş zamanını döndüren bir fonksiyon yazın


14

Meydan okuma

Fiil olan bir argümanı alan ve fiilin geçmiş zamanını döndüren bir fonksiyon yazın. (Fiilin düzenli olduğunu varsayın)

Geçmiş zaman

Not: y'yi ünsüz ya da sesli harf olarak düşünmeyin.

Normalde, edfiilin bitiminden sonra eklemek , fiilin geçmiş zamanını yapar.

Örn: jumpjumped, askasked

Ancak, başka kurallar da vardır.

  • Verilen fiilin son karakteri ise eekleyin d.

    Örn: loveloved, movemoved

  • Fiil bir ünsüz + ile sona edilirse y, o zaman değiştirmek yiçin i, ve eklemek ed.

    Örn: studystudied, crycried

  • Ancak, fiil bir sesli harf + ile bitiyorsa y, ekleyin ed.

    Örn: playplayed, staystayed

  • Bir fiil bir sesli harf ve ünsüzle sonlandırılırsa, ünsüz bir kez daha yazıp ekleyin ed.

    Örn: stopstopped, planplanned

  • Bununla birlikte, bir fiil birden çok sesli harf + bir ünsüz veya tek sesli harf + çoklu ünsüzlerle sonlandırılırsa, ekleyin ed.

    Örn: looklooked, jumpjumped

Daha fazla kural var ama sadece yukarıdaki kurallara dikkat edelim. Örneğin, yukarıdaki kurala göre, visitvisitted.

kazanan

Bu kod golf olduğundan, geçmiş zamanları doğru döndüren en kısa kod kazanır.

Örnek (JS, 127)

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


Şimdi bu güzel bir meydan okuma.
FUZxxl

ters stemming! ilginç! Eve döndüğümde denemeye çalışacağım :)
DallaRosa

1800 karakterden kısa olan herhangi bir çözüm yanlıştır (düzensiz fiiller).
Quandary

@Quandary Bu yüzden '(Fiilin düzenli olduğunu varsayalım' 'dedim
JiminP

@Quandary: Pek doğru değil ... Belisarius'un cevabına bakınız .
Simon

Yanıtlar:


6

sed, 76 karakter

Bir sed komut dosyası bu sorunun bir işlevi olarak sayılıyor mu?

s/\([^aeiou]\)y$/\1i/
s/\([^aeiou][aeiou]\)\([^aeiouy]\)$/\1\2\2/
s/e\?$/ed/

4

Mathematica 43 karakter

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

Kullanımı:

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

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

Ayrıca:

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

{"bought", "ran", "swam"}

Bir sözlük aramasının biraz hile olduğunu düşünmüyor musunuz? :-)
Simon

3
@Simon Kesinlikle hayır. WordData dilin bir parçasıdır :)
Dr. belisarius

3

Harika - 111 karakter

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']

2

Perl 5 (82 karakter):

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

Eminim geliştirilebilir.


2

C - 120 119 karakter

Tipik C stilinde, f işlevi, arayanın en fazla üç karakter için yeterli alan ayırdığını varsayarak bir dize arabelleğini günceller. İkinci argüman 0 olarak verilmelidir. Genel durum değişkeninin bildirimi ltoplam karakter sayısına dahil edilir.

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

Açıklama: İşlev, karakterler üzerinde yinelemeli olarak yinelenir. İkinci argüman i, önceki üç karakterden hangisinin alt üç bitinde ünsüz olduğunu kodlar. Dizenin sonunda, eğer i==5son üç karakter bir ünsüz, bir sesli harf ve bir ünsüz ise ve bu nedenle son karakter çoğaltılmalıdır. Benzer şekilde, bit 1 i, ikinci ile son arasındaki karakterin ünsüz olduğunu ve son karakterin "y" olduğunu gösteriyorsa, "y" yerine "i" gelir.


1

Scala 199273 karakter

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

çağırma:

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

İlk yaklaşımım if-else-cascade öğesini bir listeye => bir işleve taşıyarak çok daha uzundu:

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

Belki de yaklaşım ilginçtir. Degolfed ve açıkladı:

// 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")
  ))}

0

Ruby, 101 karakter

Muhtemelen daha küçük olabilir.

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

Kullanımı:

f("try")  #=> "tried"
f"call"   #=> "called"

Daha f=->(x){...}kısa kod almak için Ruby 1.9 lambda sözdizimini kullanın. Ayrıca aeiouyIMHO sabit olmalıdır.
Hauleth

0

Kaka - 72 karakter

f[s]s^6pow>4<<last&8*(/"ed""id""eid"/|out|flush)+rep'y'1-2-3"aeiou"ord#s

0

Python - 147

def f (v): T, x, m = 'aeiou', "ed", v [-1]; T ve m cinsinden dönüş [[[v + x, v + m + x] [v [-2] ve v [-3] T'de değil], [v + x, v [: - 1] + "ied"] [v [-2] T'de değil]] [m == 'y'], v + "d "] [m == 'e']  
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.