Do kompletu przykładów programów bez średników brakuje nam już tylko C#. C++ jest, Java jest, teraz czas na język Microsoftu ;)
Jeżeli ktoś nie zna jeszcze gry w "bum" niech zajrzy do tego posta:
http://wojtek-m.blogspot.com/2010/03/program-w-cc-bez-uzycia-srednikow.html.
Oryginalny program w C# grający w tą grę od 1 do 100 wygląda tak:
using System;
class BumGame
{
public static void Main(string[] args)
{
for (int i = 1; i <= 100; i++)
{
if (i % 3 == 0 || i % 5 == 0)
{
Console.WriteLine("BUM");
continue;
}
int j;
for (j = 1; j <= i; j *= 10)
{
int digit = (i / j) % 10;
if (digit == 3 || digit == 5)
{
Console.WriteLine("BUM");
break;
}
}
if (j > i)
{
Console.WriteLine(i);
}
}
}
}
Czas usunąć średniki ;) Maina niestety nie udało mi się usunąć... jeszcze ;)
Opracowując ten program opierałem się na tym dla Javy (http://wojtek-m.blogspot.com/2010/03/program-w-javie-bez-main.html) - i jak zwykle bez pomysłu z konstruktorem nie dałbym rady ;) Więc może najpierw program, a potem szczegóły :) Udało mi się go zrobić w 2 wersjach, różniących się obsługą wypisywania na standardowe wyjście :P
Wersja z asynchronicznym wyjściem:
class NoSemicolons
{
public static void Main(string[] args)
{
if (new NoSemicolons(0, 0, 0, new object()) == null)
{
}
}
public NoSemicolons(int i, int j, int k, object x)
{
if ((i = 1) == 0)
{
}
while (i <= 100)
{
if ((k = 0) == 0)
{
}
if (i % 3 == 0 || i % 5 == 0)
{
if (System.Console.OpenStandardOutput().BeginWrite(new byte[] { (byte)'B', (byte)'U', (byte)'M', (byte)'\n' }, 0, 4, null, x) == 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.Console.OpenStandardOutput().BeginWrite(new byte[] { (byte)'B', (byte)'U', (byte)'M', (byte)'\n' }, 0, 4, null, x) == null)
{
}
if ((k = 1) == 0)
{
}
}
if (k == 0)
{
if ((j *= 10) == 0)
{
}
}
}
if (j > i)
{
if (i < 10)
{
if (System.Console.OpenStandardOutput().BeginWrite(new byte[] { (byte)(i + '0'), (byte)'\n' }, 0, 2, null, x) == null)
{
}
}
else
{
if (System.Console.OpenStandardOutput().BeginWrite(new byte[] { (byte)(i / 10 + '0'), (byte)(i % 10 + '0'), (byte)'\n' }, 0, 3, null, x) == null)
{
}
}
}
}
if (++i == 0)
{
}
}
if (System.Console.OpenStandardOutput().BeginWrite(new byte[] { }, 0, 0, null, x) == null)
{
}
}
}
Wykorzystujemy tutaj asynchroniczne wypisywanie na ekran metodą BeginWrite - tylko ta metoda wypisująca cokolwiek na ekran zwraca coś innego od void, dzięki czemu można jej użyć w ifie ;) Ponieważ jednak jest ona asynchroniczna, to potrzebujemy obiektu synchronizującego - tutaj jest to x. Asynchroniczność może też spowodować zakończenie programu przed wypisaniem wszystkiego na ekran - dlatego po pętli dodane zostało wypisywanie "niczego".
Dodatkowym problemem metody BeginWrite jest to, że przyjmuje ona surową tablicę bajtów - jeżeli chcemy wypisać coś bardziej skomplikowanego niż stały napis to powodzenia ;) Ja dla wypisywania liczby musiałem zrobić dodatkowego ifa, a skończyło się na jednym tylko dzięki temu, że wiedziałem iż przebiegów pętli jest 100, a setka jest "BUM" ;)
Można też spróbować wypisywać na ekran innym sposobem - wywołując metodę Console.Out.WriteLine z użyciem refleksji:
class NoSemicolons
{
public static void Main(string[] args)
{
if (new NoSemicolons(0, 0, 0) == null)
{
}
}
public NoSemicolons(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 (typeof(System.IO.TextWriter).InvokeMember("WriteLine",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.InvokeMethod,
System.Type.DefaultBinder, System.Console.Out,
new object[] { "BUM" }) == 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 (typeof(System.IO.TextWriter).InvokeMember("WriteLine",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.InvokeMethod,
System.Type.DefaultBinder, System.Console.Out,
new object[] { "BUM" }) == null)
{
}
if ((k = 1) == 0)
{
}
}
if (k == 0)
{
if ((j *= 10) == 0)
{
}
}
}
if (j > i)
{
if (typeof(System.IO.TextWriter).InvokeMember("WriteLine",
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.InvokeMethod,
System.Type.DefaultBinder, System.Console.Out,
new object[] { i }) == null)
{
}
}
}
if (++i == 0)
{
}
}
}
}
Wykorzystywanie refleksji jest o wiele bardziej elastyczne - wywołujemy normalną metodę WriteLine, a nie jakieś dziwy. No i możemy w ten sposób wywołać prawie każdą metodę ;)
wtorek, 13 lipca 2010
Subskrybuj:
Komentarze do posta (Atom)
w javie to wyglądało lepiej :D
OdpowiedzUsuń