Ostatnio padło wyzwanie - napisać program bez użycia funkcji main w Javie. Taki komentarz pojawił się przy okazji programu w C bez średników - http://wojtek-m.blogspot.com/2010/03/program-w-cc-bez-uzycia-srednikow.html ;)
Hm, stwierdziłem że podbije poziom trudności i w Javie też ani jeden średnik nie zagości! Co będzie trudniejsze niż w C, bo Java jest bardziej "uporządkowana".
Oryginalny program (do znanej już gry w "bum" - osoby nie w temacie niech zerkną do powyżej podanego posta):
public class BumGame {
public static void main(String[] args) {
for (int i = 1; i <= 100; i++) {
if (i % 3 == 0 || i % 5 == 0) {
System.out.println("BUM");
continue;
}
int j;
for (j = 1; j <= i; j *= 10) {
int digit = (i / j) % 10;
if (digit == 3 || digit == 5) {
System.out.println("BUM");
break;
}
}
if (j > i) {
System.out.println(i);
}
}
}
}
Program można uruchomić normalnie bez funkcji main pisząc cały kod w statycznym bloku inicjalizującym - trzeba tylko na koniec napisać System.exit(0), aby program mógł się uruchomić. I tak otrzymujemy:
public class NoMain {
static {
for (int i = 1; i <= 100; i++) {
if (i % 3 == 0 || i % 5 == 0) {
System.out.println("BUM");
continue;
}
int j;
for (j = 1; j <= i; j *= 10) {
int digit = (i / j) % 10;
if (digit == 3 || digit == 5) {
System.out.println("BUM");
break;
}
}
if (j > i) {
System.out.println(i);
}
}
System.exit(0);
}
}
Można to normalnie uruchomić ("java NoMain" z linii komend) mimo iż brak metody main :)
OK... Ale jak się pozbyć średników? Z pomocą przyjdzie nam refleksja :) I metoda printf, nowość w Javie 5. Niestety mimo pary prób, nadal nie udało mi się usunąć średnika niezbędnego przy deklaracji zmiennej lokalnej :( Więc o to program z 1 średnikiem:
public class NoMainNoSemicolon {
static {
int flag, j, i; // pechowy średnik
if ((i = 1) == 0) {
}
while (i <= 100) {
if ((flag = 0) == 0) {
}
if (i % 3 == 0 || i % 5 == 0) {
if (System.out.printf("BUM\n") == null) {
}
if ((flag = 1) == 0) {
}
}
if (flag == 0) {
if ((j = 1) == 0) {
}
while (j <= i && flag == 0) {
if ((i / j) % 10 == 3 || (i / j) % 10 == 5) {
if (System.out.printf("BUM\n") == null) {
}
if ((flag = 1) == 0) {
}
}
if (flag == 0) {
if ((j *= 10) == 0) {
}
}
}
if (j > i) {
if (System.out.printf(i + "\n") == null) {
}
}
}
if (++i == 0) {
}
}
try {
if (Runtime.getRuntime().getClass().getDeclaredMethod("exit", int.class).invoke(Runtime.getRuntime(), 0) == null) {
}
} catch (Exception e) {
}
}
}
EDIT:
Dla osób rzadko czytających komentarze, oto wersja programu, która nie wykorzystuje ani jednego średnika - tak jak zaproponował to Herbi :)
Pomysł genialny - nie można wykorzystać zmiennych lokalnych, ale argumenty metody można definiować bez użycia średnika. Cały nasz kod przenosimy więc do metody - jednakże nie może to być ani metoda zwracająca void (bo takiej nie uruchomimy w if-ie, bo void nie można z niczym porównać) ani zwracająca cokolwiek, bo po return musi być średnik.
Rozwiązanie to zastosowanie konstruktora - jest to metoda, która zwraca referencję (po zastosowaniu operatora new), a nie potrzebuje return :)
Kod, bez ani jednego średnika:
public class NoMainReallyNoSemicolon {
public NoMainReallyNoSemicolon(int i, int j, int k) {
if ((i = 1) == 0) {
}
while (i <= 100) {
if ((k = 0) == 0) {
}
if (i % 3 == 0 || i % 5 == 0) {
if (System.out.printf("BUM\n") == null) {
}
if ((k = 1) == 0) {
}
}
if (k == 0) {
if ((j = 1) == 0) {
}
while (j <= i && k == 0) {
if ((i / j) % 10 == 3 || (i / j) % 10 == 5) {
if (System.out.printf("BUM\n") == null) {
}
if ((k = 1) == 0) {
}
}
if (k == 0) {
if ((j *= 10) == 0) {
}
}
}
if (j > i) {
if (System.out.printf(i + "\n") == null) {
}
}
}
if (++i == 0) {
}
}
}
static {
if (new NoMainReallyNoSemicolon(0, 0, 0) != null) {
try {
if (Runtime.getRuntime().getClass().getDeclaredMethod("exit", int.class).invoke(Runtime.getRuntime(), 0) == null) {
}
} catch (Exception e) {
}
}
}
}
wtorek, 16 marca 2010
Subskrybuj:
Komentarze do posta (Atom)
Muszę przyznać, że z tą refleksją to nieźle rozkminiłeś, ale nadal jest jeden średnik, a da się napisać program bez średnika i bez maina - wystarczy wykorzystać konstruktor (bo funkcja, żeby móc ją porównać, musi coś zwracać, a return musi się kończyć średnikiem), poniżej przykład :)
OdpowiedzUsuńpublic class NoMainNoSemicolon {
NoMainNoSemicolon(int flag, int j, int i) {
if ((i = 1) == 0) {
}
while (i <= 100) {
if ((flag = 0) == 0) {
}
if (i % 3 == 0 || i % 5 == 0) {
if (System.out.printf("BUM\n") == null) {
}
if ((flag = 1) == 0) {
}
}
if (flag == 0) {
if ((j = 1) == 0) {
}
while (j <= i && flag == 0) {
if ((i / j) % 10 == 3 || (i / j) % 10 == 5) {
if (System.out.printf("BUM\n") == null) {
}
if ((flag = 1) == 0) {
}
}
if (flag == 0) {
if ((j *= 10) == 0) {
}
}
}
if (j > i) {
if (System.out.printf(i + "\n") == null) {
}
}
}
if (++i == 0) {
}
}
}
static {
if (new NoMainNoSemicolon(1, 2, 3) != null) {
try {
if (Runtime.getRuntime().getClass().getDeclaredMethod("exit",
int.class).invoke(Runtime.getRuntime(), 0) == null) {
}
} catch (Exception e) {
}
}
}
}
Genialne :D
OdpowiedzUsuńTo teraz pozostało tylko napisać program w javie, który nie będzie miał nawiasów klamrowych - jak myślisz, da się? :]
OdpowiedzUsuńsuper rozwiązanie z tym konstruktorem!
OdpowiedzUsuń