Ceylon, 1431 , 764 , 697 , 571 , 547 , 538 , 501 , 493 , 467 , 451
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.hash.get(b))1});}
To był oryginalny, nie golfisty:
Integer footprintCharacter(Integer b) {
return sum({0, for(i in 0..7) if(b.get(i)) 1 });
}
Integer footPrintString(String s) {
if(s == "test") {return 0;}
return sum({0, for(c in s) footprintCharacter(c.integer)});
}
shared void footprint() {
if(exists s = process.arguments[0]) {
print(footPrintString(s));
} else {
print("This program needs at least one parameter!");
}
}
To pobiera argument z parametru wiersza poleceń ... proces.arguments jest (być może pustą) sekwencją ciągów, więc przed użyciem jednego z nich musimy sprawdzić, czy rzeczywiście istnieje. W innym przypadku wysyłamy komunikat o błędzie (nie jest to wymagane przez pytanie i zostanie wyrzucone w następnych wersjach).
sumFunkcja Cejlonu przyjmuje niepustą iterowalną część jakiegoś typu, który musi spełniać Summable, tj. Ma plusmetodę taką jak Liczba całkowita. (Nie działa z pustymi sekwencjami, ponieważ każdy typ Summable będzie miał swoje własne zero, a środowisko wykonawcze nie ma szansy dowiedzieć się, który z nich jest przeznaczony).
Elementy łańcucha lub jednego bitu liczby całkowitej nie są niepustą iterowalną. Dlatego używamy tutaj funkcji do zbudowania iterowalności poprzez określenie niektórych elementów, a następnie „zrozumienia” (które zostanie ocenione na zero lub więcej elementów). Tak więc w przypadku znaku dodajemy je (ale tylko wtedy, gdy ustawiony jest odpowiedni bit), w przypadku ciągu dodajemy wynik znaków. (Zrozumienie zostanie ocenione tylko wtedy, gdy funkcja odbiorcza faktycznie się nad nim iteruje, a nie podczas budowania Iterable).
Zobaczmy, jak możemy to zmniejszyć. Po pierwsze, każda z funkcji jest wywoływana tylko w jednym miejscu, więc możemy je wstawić. Ponadto, jak wspomniano powyżej, pozbyć się komunikatu o błędzie. (764 punktów śladu).
shared void footprint() {
if (exists s = process.arguments[0]) {
if (s == "test") {
print(0);
} else {
print(sum({ 0, for (c in s) sum({ 0, for (i in 0..7) if (c.integer.get(i)) 1 }) }));
}
}
}
Tak naprawdę nie potrzebujemy zagnieżdżenia wewnętrznego sum, możemy to jedno wielkie zrozumienie. (To oszczędza nam 37 punktów śladu sum({0,}), a trochę więcej dla białych znaków, które i tak zostaną wyeliminowane na końcu.) To jest 697:
shared void footprint() {
if (exists s = process.arguments[0]) {
if (s == "test") {
print(0);
} else {
print(sum({ 0, for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
}
}
Możemy zastosować podobną zasadę do specjalnego "test"ciągu w postaci łańcucha: ponieważ w tym przypadku wynik wynosi 0 (tzn. Nic nie jest sumowane), możemy to zrobić tylko jako część sumy (ale musimy odwrócić warunek) . To głównie oszczędza nam print(0);trochę nawiasów klamrowych i kilka wcięć, dochodząc do 571:
shared void footprint() {
if (exists s = process.arguments[0]) {
print(sum({ 0, if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
}
Robimy to samo za pierwszym razem if, z efektem ubocznym, który teraz nie daje żadnych argumentów, a także 0nic nie robi. (Przynajmniej myślałem, że tak się stanie tutaj, zamiast tego wydaje się, że zawiesi się w wiecznej pętli? Dziwne.)
shared void footprint() {
print(sum({ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 }));
}
Możemy faktycznie pominąć tutaj funkcję ()dla tej sumfunkcji, używając alternatywnej składni wywołania funkcji , która używa {...}zamiast tego ()i wypełni wyrażenia w iterowalnych argumentach. Ma to ślad 538:
shared void footprint() {
print(sum{ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 });
}
Zastąpienie nazwy funkcji footprint(40) przez p(3) pozwala zaoszczędzić kolejne 37 punktów, co prowadzi do 501. (Nazwy funkcji Cejlonu muszą zaczynać się od małych liter, więc nie możemy uzyskać tutaj mniej niż 3 punkty).
shared void p() {
print(sum{ 0, if (exists s = process.arguments[0]) if (s != "test") for (c in s) for (i in 0..7) if (c.integer.get(i)) 1 });
}
Nazwy zmiennych s(5) i c(4), i(4) również nie są optymalne. Zamieńmy je na a(argument), d(cyfra?) I b(indeks bitów). Ślad 493:
shared void p() {
print(sum{ 0, if (exists a = process.arguments[0]) if (a != "test") for (c in a) for (b in 0..7) if (c.integer.get(b)) 1 });
}
Nie widzę żadnej optymalizacji spoza białych znaków, więc usuń niepotrzebne spacje (1 punkt za każde miejsce, dwa za każde z dwóch podziałów linii):
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.integer.get(b))1});}
Podczas przeglądania interfejsu API odkryłem, że Character.hash faktycznie zwraca tę samą wartość co jego integeratrybut. Ale ma tylko 14 punktów zamiast 30, więc schodzimy do 451!
shared void p(){print(sum{0,if(exists a=process.arguments[0])if(a!="test")for(c in a)for(b in 0..7)if(c.hash.get(b))1});}