Thread overview
Sağcı Robot
Mar 27, 2012
Salih Dinçer
Mar 27, 2012
Salih Dinçer
Mar 31, 2012
Salih Dinçer
March 28, 2012
/*
robot.d (28.03.2012)

Sorunun orijinali bir Türk üniversitesi hocasına* aittir. Kısaca, sayı doğrusu
gibi bir duvarda ki: <____-3____-2____-1____0____+1____+2____+3____>
bir robotun açık kapıyı (sayıyı) bulma çilesini azaltmamız isteniyor...:)

Açık kapı negatif numaralarda da olabileceği için her iki tarafı (Batı/Doğu)
kontrol etmesi gerekiyor. Bunun için main()'de sırayla bir o yana bir bu yana
deli gibi dönen robotumuzu kodladık. Acaba robotumuz bataryasını en iyi şekilde
kullanabilmek için hangi algoritmaya ihtiyacı var?

Kurallar:
=========
o Yapıyı (robot{}) değiştirmemek kaydıyla main() içinde kod kullanımı serbest!
o Ancak hafızadan rasgele üretilen sayıyı tespit etmek yasak; bunu bilmiyor...
o Sadece doğru kapıyı bulduğunda (girdi = true) döngünün sonlanması yeterli ve
o Test için rasgele aralık genişletilebilir veya sabit bir sayı seçilebilir.

Dip Not: Robotumuzun açık kapıyı bulma dışında bir sorunu daha var! Hep sağ
tarafına dönebiliyor. Dolayısıyla solunda dönmesi için 3 değerini parametre
olarak vermeniz yetiyor. Zaten asıl enerjiyi ileri/geri gitmede harcıyor...

Programlama: Salih Dinçer
*/
import std.stdio, std.random;

enum yön { Kuzey, Doğu, Güney, Batı }

struct Robot {
   // Tam tur dönerken ve 1 metre giderken harcadığı enerji 1 mWatt
   double harcananKw = 0;
   yön yönü;
   int konumu;
   int kapısı;
   bool girdi = false;

   void sağaDön(int xKere) {
       for (; xKere > 0; xKere--)
       {
           if (yönü != yön.Batı) {
               yönü++;
           } else {
               yönü = yön.Kuzey;
           }
           harcananKw += 0.00025;
       }
       if (yönü == yön.Güney && konumu == kapısı)
       {
           girdi = true;
       }
   }

   void xMetreGit(int xMetre) {
       if (yönü == yön.Doğu)
       {
           konumu += xMetre;
       }
       if (yönü == yön.Batı)
       {
           konumu -= xMetre;
       }
       harcananKw += xMetre/1000;

       writef("%.3f Kw. harcandı, (%s): %d numaralı kapıda         \r",
                   this.harcananKw/1000,
                   this.yönü,
                   this.konumu);
   }
}

void main() {
   Robot robot;
   robot.kapısı = uniform (int.min>>16, int.max>>16);
   int xSay = 0;

   robot.sağaDön(2);   // Güneye bakıyor...
   while (!robot.girdi)
   {
       robot.sağaDön(xSay % 2 == 1 ? 1 : 3);
       // Çiftse batı (-), tekse doğu (+) duvarına dönüyor...
       robot.xMetreGit(++xSay); // Kontrol etmediği kapıya gidiyor...
       robot.sağaDön(xSay % 2 == 1 ? 1 : 3);
       // Tekrar güneye bakıyor ve kontrol ediyor...
   }
   writeln();
}

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 28, 2012

Alıntı (acehreli):

>

Güzelmiş. :) (Aslında bu sorunun benzerini teyp kayıt kafasının belirli bir veriyi araması olarak duymuştum.)
Hoca bunu Java'da tasarlamış ve öğrencilerine soruyormuş. Çözümü bulmamanız için ismini vermeyeceğim ama IBM'de çalışmış ve Türkiye'de ikamet ediyor. Çözümü ben de okumadım sadece sorunun yukarıdaki çözümünü kodladım. Hem adil olsun hem de kendi bulduğumuz çözüm matematiksel olarak bulunan ile ne kadar uyuşacak onu merek ediyorum...;)

Alıntı (acehreli):

>

Denemedim ama gözüme şu çarptı: xMetre/1000 ;)
Sihirli sayıdan dolayı mı? Orada aslında Kw (kilowatt) gösterimi için kullanıldı. Kod da sıkıntı yok gibi...

Bu arada ölçüm için aşağıdaki gibi sabit bir sayı belirleyebiliriz. Çünkü tam 1000 KWatt enerji harcamış oluyor. Aslında bu uçuk güç değeri bize, algoritmanın ne kadar akıllıca tasarlanması gerektiğini gösteriyor!

robot.kapısı = -22611;// uniform (int.min>>16, int.max>>16);

Ben şimdi düşünmeye başladım bile, başarılar...:)

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 28, 2012

Güzelmiş. :) (Aslında bu sorunun benzerini teyp kayıt kafasının belirli bir veriyi araması olarak duymuştum.)

Denemedim ama gözüme şu çarptı: xMetre/1000 ;)

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 28, 2012

Alıntı (Salih Dinçer):

>

Alıntı (acehreli):

>

Denemedim ama gözüme şu çarptı: xMetre/1000 ;)
Sihirli sayıdan dolayı mı? Orada aslında Kw (kilowatt) gösterimi için kullanıldı. Kod da sıkıntı yok gibi...

Hassaslık ne kadar önemli bilmiyorum ama tamsayı bölümünde sonucun virgülden sonrası kalmaz diye hatırlatmak istemiştim.

Ali

--
[ Bu gönderi, http://ddili.org/forum'dan dönüştürülmüştür. ]

March 31, 2012

Açıkçası, bu tür sayılarda virgül (ingilizce nokta) kullanmamanın ondalıklı kısmı uçurduğunu bilmiyordum. Bu durumda v2'yi yayınlamalıyım:

Alıntı:

>
> struct RobotV2 {
>     // Tam tur dönerken ve 1 metre giderken harcadığı enerji 1 mWatt
>     double harcananMw = 0;
>     yön yönü;
>     int konumu, kapısı = -22611; // Varsayılan değer ~ 1 Mega Watt !!!
>     bool girdi = false;
>
>     void xYöneDön(int xKere) {
>         for (; xKere > 0; xKere--) {
>             if (yönü != yön.Batı) yönü++;
>             else yönü = yön.Kuzey;
>
>             harcananMw += 0.00000025;
>         }
>         if (yönü == yön.Güney && konumu == kapısı) girdi = true;
>      }
>
>     void xMetreGit(int xMetre) {
>         if (yönü == yön.Doğu) {
>             konumu += xMetre;
>             harcananMw += xMetre/1000_000.0;
>         }
>         if (yönü == yön.Batı) {
>             konumu -= xMetre;
>             harcananMw += xMetre/1000_000.0;
>         }
>
>         writef("%.6f Mega Watt harcandı, (%s): %d numaralı kapıda         \r",
>                                 this.harcananMw/1000, this.yönü, this.konumu);
>     }
> }
> ```

>
Bu sayede bir hatayı daha düzelttim. Gerçi robot baktığı yer dışında bir yöne gitmesi saçma ama yanlışlıkla bakmadığı bir yöne gitmesi istenirse (gidemediği halde!) fazladan enerji harcayacak. Bu da soruyu çözenler arasında bir karışıklığa neden olabilir. O yüzden lütfen ikinci yapıyı dikkate alınız. Ayrıca iki düzeltme daha yapmalıy(d)ım...:)

1.'si Chris hoca ile görüştüm (evet, sorunun orijinin Chris Stephenson'a aitti) meğer iki farklı sorusunu karıştırmışım! Çünkü Ekşi Sözlük'te kendisini tanıyan öğrencilerinin biri sadece sağa dönebilen ve sola dönmesi için aynı hareketi üç defa tekrarlayan robottan bahsetmişti. Ben de doğal olarak o robotun aynı sorudaki başka bir ayrıntısı zannetmiştim. Özetle dileyen sola dön diye de bir işlev kurabilir. Ama zaten dönerken çok fazla bir enerji harcamıyor; asıl etki eden mekik gibi bir batıya bir doğuya gidip gelmesi.

2.'si ise yine diğeri ile bağlantılı ve böyle daha iyi olacağını düşündüm. Çünkü sağa dön yerine 'xYöneDön()' işlevi olarak isim değiştirdim. Böylece dileyen 3 sayısını bir sabit (örn. sağaDön) olarak tanımlayıp daha insancıl bir kod yazabilir. Sanırım böylesi hem daha basit oldu hem de çok orijinal. Dolayısıyla bu soruyu soran sanırım tarihte ilk forum burası oldu...:)

Unutmuşum...

3.'sü, evet bir üçüncü (belki 4, 5!) düzeltme daha yaptım. Robot bir birim hareket etmek için 1 watt enerji harcıyor. Ancak dikkat ettiniz mi bilmem sorunun en basit çözümünde int.max durumunda double türü yetmiyor. O yüzden 1 milyona böldüm ve küçük denemeler için virgülden sonraki hassasiyeti 3 hane daha arttırdım. Özetle böyle daha iyi oldu, değil mi?

**Dip Not:** Megawatt'larca enerji harcanması gerçekten çok utopik bir durum. Tabi bu tek bir robot için geçerli yoksa sorunun en iyi çözümü iki robot ve aralarındaki wi-fi haberleşme olacaktır. Biri bulduğunda diğerine haber verecek. Bu durumda lüften soruyu çözerken multitasking komutlarını kullanmayınız; bunlar da yasak...:)

Başarılar...

-- 
[ Bu gönderi, <http://ddili.org/forum>'dan dönüştürülmüştür. ]