Помощ - Търси - Регистрирани - Календар
Пълна версия: лесна задачка
UniBG Forums > Дискусии > Dexter's Lab > Програмиране
dlh
Докато играх една игра се натъкнах на интересен пъзел, който с малко логика би могъл да се реши с програма. Attach-вам screenshot от играта.

Задачката е да се напише алгоритъм, който да изкара всички възможни отговори на пъзела wink.gif

За улеснение, думата почва отляво надясно, отгоре надолу smile.gif
Guest
offtopic

koq e igrata, padam si po takiva
dlh
Safecracker
demond
при положение че явно никой тука не е чувал за пермутации (освен онгеборен), едва ли ще дочакаш решение ми се струва
magdanoz
dlh nikaf gamer ne si bate =)
dlh
QUOTE(demond @ Aug 6 2006, 10:14 PM)
при положение че явно никой тука не е чувал за пермутации (освен онгеборен), едва ли ще дочакаш решение ми се струва
*


sad, but true...

QUOTE(magdanoz @ Aug 6 2006, 11:25 PM)
dlh nikaf gamer ne si bate =)
*


?smile.gif
Narf
QUOTE(demond @ Aug 6 2006, 10:14 PM)
при положение че явно никой тука не е чувал за пермутации (освен онгеборен), едва ли ще дочакаш решение ми се струва
*


Мдам.
Опитах се да напиша решението, но с ограничените си знания успях да измисля начин да генерирам само около 90-тина варианта.
Narf
Е, след лека главоблъсканица все пак стигнах до решението:

CODE
<?php
$keys = array(
       0 => array(0 => 'G', 1 => 'F', 2 => 'D', 3 => 'L'),
       1 => array(0 => 'O', 1 => 'T', 2 => 'I', 3 => 'N'),
       2 => array(0 => 'K', 1 => 'C', 2 => 'M', 3 => 'R'),
       3 => array(0 => 'U', 1 => 'A', 2 => 'P', 3 => 'C'),
       4 => array(0 => 'Z', 1 => 'W', 2 => 'T', 3 => 'N'),
       5 => array(0 => 'S', 1 => 'A', 2 => 'B', 3 => 'E'),
);
$combinations = (6 * 6 * 4 * 4);
$filename = 'db.txt';
if (!file_exists($filename)) {
 fopen($filename, 'w+');
 fclose($filename);
}
$count = 1;
while ($count <= $combinations) {
 $c = $keys[0][rand(0,3)].$keys[1][rand(0,3)].$keys[2][rand(0,3)].$keys[3][rand(0,3)].$keys[4][rand(0,3)].$keys[5][rand(0,3)];
 $data = file($filename);
 $hits = 0;
 foreach ($data as $content) {
   if ($content == $c) {
     $hits++;
   }
 }
 if ($hits == '0') {
   $count++;
   $file = fopen($filename, 'a');
   fwrite($file, $c.'|');
   fclose($file);
 }
}
$count = 1;
while ($count <= $combinations) {
 $data = file($filename);
 foreach ($data as $content) {
   $var = explode('|', $content);
 }
 echo $count++.' '.$var[$count].'<br>';
}
?>


Може да има проблеми с отварянето на файла, но това си зависи от настройките на сървъра. smile.gif
demond
всъщност броя на комбинациите е 4 на 6-та степен = 4096; това следва от формулата за пермутации с повторение, избрани от n елемента в r позиции N = pow(n,r)

ето един алгоритъм за генериране на пермутации (естествено измислен не от мен а от Кнут), написан в псевдокод:
CODE
sub permutation(k, r) {
   var int factorial := 1;
   for j= 2 to r {
      factorial := factorial * (j-1);
      swap(s[j-((k \ factorial) mod j)], s[j]);
   }  
}

където \ значи целочислено делене, k е к-тата пермутация и 0 <= k < r! (r факториел)

обобщаването на този код за pool от n елемента оставям на любознателния читател smile.gif
Narf
Интересно тогава как кода ми генерира над 5000 уникални комбинации. smile.gif
dlh
QUOTE(demond @ Aug 8 2006, 06:17 AM)
всъщност броя на комбинациите е 4 на 6-та степен = 4096; това следва от формулата за пермутации с повторение, избрани от n елемента в r позиции N = pow(n,r)

ето един алгоритъм за генериране на пермутации (естествено измислен не от мен а от Кнут), написан в псевдокод:
CODE
sub permutation(k, r) {
   var int factorial := 1;
   for j= 2 to r {
      factorial := factorial * (j-1);
      swap(s[j-((k \ factorial) mod j)], s[j]);
   }  
}

където \ значи целочислено делене, k е к-тата пермутация и 0 <= k < r! (r факториел)

обобщаването на този код за pool от n елемента оставям на любознателния читател smile.gif
*


да живее висшата математика wink.gif

QUOTE(Narf @ Aug 8 2006, 01:13 PM)
Интересно тогава как кода ми генерира над 5000 уникални комбинации. smile.gif
*


защото е грешен wink.gif

ето моя, който написах преди да постна задачката
не се гордея особено с него smile.gif

CODE
<?php

$a = array('g','d','l','f');
$b = array('o','t','i','n');
$c = array('k','c','m','r');
$d = array('u','a','p','c');
$e = array('z','w','t','n');
$f = array('s','a','b','e');
$i = 0;

foreach ($a as $x) {
 $word[] = $x;
 foreach ($b as $y) {
   $word[] = $y;
   foreach ($c as $z) {
     $word[] = $z;
     foreach ($d as $j) {
       $word[] = $j;
       foreach ($e as $k) {
         $word[] = $k;
         foreach ($f as $l) {
           echo implode($word). $l ."<br/>";
           $i++;
         }
         array_pop($word);
       }
       array_pop($word);
     }
     array_pop($word);
   }
   array_pop($word);
 }
 $word = array();
}

echo "<hr>Count: $i";

?>
Narf
Дам, като се замисля, не са уникални.

CODE
<?php
$keys = array(
       0 => array(0 => 'G', 1 => 'F', 2 => 'D', 3 => 'L'),
       1 => array(0 => 'O', 1 => 'T', 2 => 'I', 3 => 'N'),
       2 => array(0 => 'K', 1 => 'C', 2 => 'M', 3 => 'R'),
       3 => array(0 => 'U', 1 => 'A', 2 => 'P', 3 => 'C'),
       4 => array(0 => 'Z', 1 => 'W', 2 => 'T', 3 => 'N'),
       5 => array(0 => 'S', 1 => 'A', 2 => 'B', 3 => 'E'),
);
$combinations = (4 * 4 * 4 * 4 * 4 * 4);
$filename = 'db.txt';
if (!file_exists($filename)) {
 fopen($filename, 'w+');
 fclose($filename);
}
$count = 1;
while ($count <= $combinations) {
 $c = $keys[0][rand(0,3)].$keys[1][rand(0,3)].$keys[2][rand(0,3)].$keys[3][rand(0,3)].$keys[4][rand(0,3)].$keys[5][rand(0,3)];
 $data = file($filename);
 $hits = 0;
 foreach ($data as $content) {
   $count2 = $count;
   $var = explode('|', $content);
   if ($var[$count2++] == $c) {
     $hits++;
   }
 }  if ($hits == '0') {
   $count++;
   $file = fopen($filename, 'a');
   fwrite($file, $c.'|');
   fclose($file);
 }
}
$count = 1;
while ($count <= $combinations) {
 $data = file($filename);
 foreach ($data as $content) {
   $var = explode('|', $content);
 }
 echo $count++.' '.$var[$count].'<br>';
}
?>


Това вече е fix-нато и би трябвало да работи правилно, но се изпълнява прекалено бавно и резултата е:

QUOTE
Fatal error: Maximum execution time of 60 seconds exceeded in /var/www/riddle.php on line 23
dlh
set_time_limit(0);

но според мен някой loop не ти е наред
lorddoskias
ako ne drugo tova me zapali po taq oblast ot matematikata i sled 4etene vyv wikipedia i malko ruski spravo4nici (hail father) imam nqkolko vyprosa:

Za6to sa vi permutacii? Te ne se li izpolzvat kogato reda ima zna4enie toest ako imahme 6 butona vseki s ednakvi simvoli ne seli izpolzvat permutacii togava?

Tuk ne trqbvat li kombinacii s povtorenie?

I pak ne sym siguren 4e trqbvat kombinacii/permutacii tyi kato (pone v wikipedia) vse se govori ako ima6 kraen broj obekti, da re4em 10 i ako isak6 da vzeme6 3 da re4em, i da razbere6 krainiqt broj kombinacii koito moje6 da napravi6. Ama tyi ili ina4e moje6 da si vzeme6 i 10-te i pak da razbere6 kraen broj kombinacii sys vsi4kite.

Demond: ti kazva6 4e krainqit broj e 4^6, a ne e li 6^4, toest 6 obekta po 4 vyzmojni kombinacii vsi4ki. ili moje bi 6^4!

vypreki vsi4ko ne sym siguren v gornoto, vse pak pitam smile.gif a i sym mnogo dale4 da go u4a tova po redovnata programa
lorddoskias
narf 6to ne go naprai6 $combinations = 4^6; ? vypreki 4e mislq 4e sa 6^4? i pak mislq 4e tova ne e vqrno:)
Narf
QUOTE(dlh @ Aug 8 2006, 02:51 PM)
set_time_limit(0);

но според мен някой loop не ти е наред
*


Не, просто при ползването на rand() се получават адски много повтарящи се комбинации, които забавят доста процеса.

QUOTE(lorddoskias @ Aug 8 2006, 03:48 PM)
narf 6to ne go naprai6 $combinations = 4^6; ? vypreki 4e mislq 4e sa 6^4? i pak mislq 4e tova ne e vqrno:)
*


В php няма оператор '^'. (Arithmetic operators)
Гост_sof
QUOTE(lorddoskias @ Aug 8 2006, 03:48 PM)
narf 6to ne go naprai6 $combinations = 4^6; ? vypreki 4e mislq 4e sa 6^4? i pak mislq 4e tova ne e vqrno:)
*


Kombinaciite sa 4^6:

CODE
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my @figs = (
       ['A', 'B', 'C', 'D'],
       ['E', 'F', 'G', 'H'],
       ['I', 'J', 'K', 'L'],
       ['M', 'N', 'O', 'P'],
       ['Q', 'R', 'S', 'T'],
       ['U', 'V', 'W', 'X'],
);

my @return = ('');
foreach my $fig (@figs) {
       my @return_t;

       foreach my $letter_f (@{$fig}) {
               foreach my $letter_a (@return) {
                       push(@return_t, $letter_a . $letter_f);
               }
       }

       @return = @return_t;
}

print Dumper(@return);


Bih kazal 4e za poreden pyt sym razo4arowan ot powedenieto na demond... (ne 4e gledam foruma tolkowa 4esto)
Stillness
QUOTE(dlh @ Aug 5 2006, 11:07 PM)
Докато играх една игра се натъкнах на интересен пъзел, който с малко логика би могъл да се реши с програма. Attach-вам screenshot от играта.

Задачката е да се напише алгоритъм, който да изкара всички възможни отговори на пъзела wink.gif

За улеснение, думата почва отляво надясно, отгоре надолу smile.gif
*


Всички възможни комбинации от букви или само верните отговори /ако са повече от един/? Защото ако става въпрос за всички възможни комбинации, то това няма да е отговор на пъзела.
Narf
QUOTE(Stillness @ Aug 8 2006, 05:57 PM)
Всички възможни комбинации от букви или само верните отговори /ако са повече от един/? Защото ако става въпрос за всички възможни комбинации, то това няма да е отговор на пъзела.
*


Всички възможни, няма начин да разбереш коя е вярната комбинация.
Stillness
Хех, в такъв случай не може да се реши пъзела с програма smile.gif
И все пак предполагам, че самата игра "реагира" само при една дума...
dlh
Надали ще може на 100%, но наблягам на думите "с малко логика" - това включва невъзможните комбинации от букви, като по този начин ще се изключат голяма част от отговорите.

sof, какво прави Data::Dumper() ?smile.gif
Гост_sof
Instaliraj edin aspell i edin diff:

CODE
#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my $dict_file = 'words.dict';
my @figs = (
      ['G', 'D', 'L', 'F'],
      ['O', 'T', 'I', 'N'],
      ['M', 'R', 'C', 'K'],
      ['U', 'C', 'A', 'P'],
      ['N', 'Z', 'W', 'T'],
      ['B', 'A', 'E', 'S'],
);

my @return = ('');
foreach my $fig (@figs) {
      my @return_t;

      foreach my $letter_f (@{$fig}) {
              foreach my $letter_a (@return) {
                      push(@return_t, $letter_a . $letter_f);
              }
      }

      @return = @return_t;
}

open(FH, '> ' . $dict_file) || die 'Cannot open file for writing: ' . $!;
foreach my $word (@return) {
       print FH $word . "\n";
}
close(FH);

system('aspell list < ' . $dict_file . ' > ' . $dict_file . '.wrong');
system('diff -druN ' . $dict_file . ' ' . $dict_file . '.wrong');
unlink($dict_file);
unlink($dict_file . '.wrong');


Output:

QUOTE
[sofit@Infected ~]$ ./puzzle.pl
--- words.dict  2006-08-08 18:59:32.000000000 +0300
+++ words.dict.wrong    2006-08-08 18:59:32.000000000 +0300
@@ -2976,7 +2976,6 @@
FNRATE
GOCATE
DOCATE
-LOCATE
FOCATE
GTCATE
DTCATE


Word: LOCATE (happy aspelling)...
Гост_sof
QUOTE(dlh @ Aug 8 2006, 06:56 PM)
Надали ще може на 100%, но наблягам на думите "с малко логика" - това включва невъзможните комбинации от букви, като по този начин ще се изключат голяма част от отговорите.

sof, какво прави Data::Dumper() ?smile.gif
*


Data::Dumper izkarwa output na slojni strukturi w 4etim wid (kato hashove, array-i, array-i ot hashowe, obekti).
dlh
Вероятно е locate, да wink.gif
Мерси smile.gif

За съжаление копчетата ми са блокирани (трябва ми карта) и не мога да пробвам... а ме мързи да нареждам един пъзел wink.gif

Скоро ще постна още една задачка от същата игра, но нея вече съм я минал wink.gif
Narf
QUOTE(Stillness @ Aug 8 2006, 06:16 PM)
Хех, в такъв случай не може да се реши пъзела с програма smile.gif
И все пак предполагам, че самата игра "реагира" само при една дума...
*


Никой не е казал, че пъзела ще се решава с програма.
На dlh просто му е дошла идеята за тази задачка, от пъзела в играта.
demond
QUOTE(lorddoskias @ Aug 8 2006, 03:41 PM)
ako ne drugo tova me zapali po taq oblast ot matematikata i sled 4etene vyv wikipedia i malko ruski spravo4nici (hail father) imam nqkolko vyprosa:

Za6to sa vi permutacii? Te ne se li izpolzvat kogato reda ima zna4enie toest ako imahme 6 butona vseki s ednakvi simvoli ne seli izpolzvat permutacii togava?


ако се абстрахираш от буквите, ще забележиш че всеки от 6-те ключа има 4 позиции които явно могат да се повтарят, и реда на които има значение; всъщност, неформално погледнато, тук става дума за комбинации, не пермутации; обаче в комбинаториката (онази област от математиката която се занимава с тези неща) е прието пермутации да се наричат такива конфигурации в които реда на елементите има значение, а комбинации - в които няма

QUOTE
Demond: ti kazva6 4e krainqit broj e 4^6, a ne e li 6^4, toest 6 obekta po 4 vyzmojni kombinacii vsi4ki. ili moje bi 6^4!


не е smile.gif даже и без да използваш формулата която споменах, лесно може да се види - близко е до ума в този конкретен случай - че общия брой на комбинациите е броя на позициите на всеки ключ (4), умножен сам по себе си толкова пъти колкото е броя на ключовете (6)
demond
QUOTE(Гост_sof @ Aug 8 2006, 05:03 PM)
Kombinaciite sa 4^6:

CODE
#!/usr/bin/perl


неефективно решение (генериращо много излишни междинни резултати), написано на грозен език; но коректно, удовлетворяващо условието на длх и най-важното - вършещо работа заедно с използването на dictionary diff (добра идея)

QUOTE
Bih kazal 4e za poreden pyt sym razo4arowan ot powedenieto na demond... (ne 4e gledam foruma tolkowa 4esto)
*


и аз бях разочарован от поведението на Мел Гибсън, но го преживях smile.gif
Guest
QUOTE(demond @ Aug 9 2006, 05:40 AM)
неефективно решение (генериращо много излишни междинни резултати), написано на грозен език; но коректно, удовлетворяващо условието на длх и най-важното - вършещо работа заедно с използването на dictionary diff (добра идея)
и аз бях разочарован от поведението на Мел Гибсън, но го преживях smile.gif
*


Interesno smile.gif koe ot wsi4ko ti se stori izlishno, towa 4e se buildva ['' . 'A'], ['' . 'B'] => ['' . 'A' . 'C'], ['' . 'B' . 'C'] ? E kato si takyw gyzar i fen na algoritmite naprawi nesto po-dobro smile.gif towa raboti byrzo i wyrshi rabota - i naj-wajnoto ne sym zagubil 4asowe da razu4awam algoritmi, prosto izpolzwah prostotata na Perl.
demond
абе гостенино заблуден,

тежкарство не е това човек да изучи (да "загуби" не часове а месеци и години) и да използва това което много по-умни и по-учени от него са измислили в течение на десетилетия, и което използват всички професионалисти; тежкарство е човек който до вчера не е бил написал "hello world", днес да си мисли и да твърди че програмката което е родила собствената му глава е достатъчно добра за да няма нужда от губене на време за учене на глупости като алгоритми

вече беше похвален че това което си направил върши работа, не не се излагай с изказвания като последното, не си толкова тъп; ако не си чувал за неща като time & space complexity на алгоритмите, просто сложи един print след push-а ти, и един print след swap-а в кода който постнах; после сравни резултатите и ще видиш кое е излишно
psycholook
Задачата изглежда интересна. Първото което ми идва на акъла е да се използва четвърична бройна система за комбинациите, понеже тя се програмира трудно, най-близката до нея е двоичната. Тогава информацията за всеки ключ ще се съдържа в два бита, т.е. за 6 ключа ще са нужни 12 бита. Понеже на езика на който писах кода няма много 12-битови променливи rolleyes.gif - използвах 16-битов word. А генератора на комбинациите е просто един for loop. Pure and simple. wink.gif
Ето това което написах набързо на the almighty pascal. :>

CODE
Program Puzzle;

Const
 Kombinacii = 4096; { 2^12 }
 Outfile = 'out.txt';
 Simvoli : Array[1..6, 1..4] of Char = (
   ('G', 'D', 'L', 'F'),
   ('O', 'T', 'I', 'N'),
   ('M', 'R', 'C', 'K'),
   ('U', 'C', 'A', 'P'),
   ('N', 'Z', 'W', 'T'),
   ('B', 'A', 'E', 'S'));

Function GetDvataBita(KoiDvaBita, OtKyde: Word): Word;
{Vrushta informaciq za daden kliuch, koqto se sudurja v dva bita}
Begin
 Dec(KoiDvaBita);

 OtKyde := OtKyde shr (KoiDvaBita*2);
 GetDvataBita := (OtKyde and $3) + 1;
End;

var i, j: Word;
   variant: string;
   f: Text;

Begin
 Assign(F, Outfile);
 Rewrite(F);

 For i:=1 to Kombinacii do Begin
   variant := '';
   For j:=1 to 6 do
     variant := variant + Simvoli[j, GetDvataBita(j, i)];

   WriteLn(F, Variant);
 End;
 Close(F);
End.
demond
psycholook, много вярно наблюдение за 4-тичната бройна система и находчиво решение с използването на готови комбинации от битове - поздравления; това може да се оптимизира така че в този частен случай да е по-бързо от класическия алгоритъм който постнах, понеже няма swaps а само индексиране

онгеборен: такива хора ти трябват за dev team, а и човека се интересува от ircd
ongeboren
QUOTE(demond @ Aug 10 2006, 04:55 AM)
psycholook, много вярно наблюдение за 4-тичната бройна система и находчиво решение с използването на готови комбинации от битове - поздравления; това може да се оптимизира така че в този частен случай да е по-бързо от класическия алгоритъм който постнах, понеже няма swaps а само индексиране

онгеборен: такива хора ти трябват за dev team, а и човека се интересува от ircd
*



mmdam smile.gif
samo za irc C e malko po-prilojim (ne che imam neshto protiv pascal, de wink.gif )

p.s. maj vse pak imalo programisti v tova zagubeno BG tongue.gif
psycholook
уаау..

в момента съм се хванал да пиша ircd на delphi(да.. смейте са) и за сега се получава. Но много бих се радвал да помогна за разработването на ircd на UniBG, след като завърша това, което аз пиша(тъкмо ще знам какво представляват ircd-тата). tongue.gif
за C ако става въпрос, също и на C пиша, но по-чесно на паскал, понеже паскал по ми харесва като език. smile.gif
Naka
думата не е locate , az q znam no da ne q kazvam ако искате smile.gif
Naka
думата не почва отгоре надоло нито отляво надясно ...
Guest
ae q mi kajete kak moga da mina o6te v vtorata staq tam kadeto ima da sglobqvam edin dolar zako mi ostavat o6te 4asti ko trqbva da gi praq ?
Това е семпла версия на форума. За да видиш пълната версия, която има повече информация, по-добра подредба и снимки, натисни тук.
Invision Power Board © 2001-2008 Invision Power Services, Inc.