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).
sum
Funkcja Cejlonu przyjmuje niepustą iterowalną część jakiegoś typu, który musi spełniać Summable
, tj. Ma plus
metodę 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 0
nic 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 sum
funkcji, 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 integer
atrybut. 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});}