Po drátě 3: Řešení úlohy č. 12

Zadání je pro změnu program. Je krásně jednoduchý a evidentně nic ošklivého nedělá (za mírně děsivou by se dala považovat snad jenom záhadná řetězcová konstanta pojmenovaná rahc ... pamětníci si jistě vzpomínají). Tak si ho zkusíme zkompilovat a spustit.

Po chvilce vypíše "Gratulujeme! Vyresili js" ... a další písmenka vypisuje pomaleji a pomaleji. Zřejmě na konci textu vypíše heslo, ale sotva to stihne do konce soutěže (nebo aspoň do konce světa).

Pojďme se mu tedy podívat na zoubky zblízka: Vnější cyklus proběhne tolikrát, kolik písmenek má zmíněná konstanta, a za každý svůj krok jedno písmenko vypíše. Jenže další dva cykly do něj vnořené mezitím ještě mnohokrát posunou pozici ve stringu, takže vůbec není jasné, které písmenko se kdy vypíše.

Nejvnořenější ze tří cyklů podezřele připomíná přičítání jedničky k i-cifernému dvojkovému číslu zapsanému po číslicích. Prostřední cyklus opakuje tuto operaci tak dlouho, než přičtení skončí s přenosem z i-tého řádu, tedy po 2i krocích. Vnější cyklus proto vypíše (2i mod N)-té písmenko, kde N je délka celého řetězce.

Program tedy stačí přepsat tak, aby rovnou počítal mocniny dvojky modulo N:

#include <stdio.h>
#include <string.h>

int main(void)
{
  const char rahc[] = "Gr atnmt!eVaietus e vyekj j!ai lsiuPvrodayorosloieeaseu znlp h u ei hlrrpisljheacmopcg e bel iinelts:";
  int n, p, q, i;
  p = 0;
  q = 1;
  n = strlen(rahc);
  for (i=1; i<n; i++)
    {
      putchar(rahc[p]);
      p = (p+q) % n;
      q = (q+q) % n;
    }
  putchar('\n');
  return 0;
}

Komentář

Špatnými řešeními vás tentokráte nepobavíme: Všichni, kdo se k této úloze dostali, ji až na triviální chyby (jako vypsání prvního písmenka stringu ještě jednou na konci) vyřešili hned správně.

Úlohu napsal Martin a zase si na tom jednou trošku procvičil základy algebry: délku řetězce je totiž potřeba zvolit tak, abychom mocninami dvojky proskákali všechny znaky, jinými slovy aby dvojka byla generátorem multiplikativní grupy modulo délka řetězce.

Re: Po drátě 3: Řešení úlohy č. 12 Festr (3. 12. 2008 - 21:25) Sbalit(1)
Bohuzel jsem nemel cas vyresit vsechny otazky, uz se tesim na dalsi soutez.

S outhle ulohou me ihned napadlo, ze se tam pocita moznina. Takto to bude efektivnejsi jeste:

q = 1;
n = strlen(rahc);
for (i=1; i<n; i++)
{
putchar(rahc[(q - 1)]);
q = (q << 1) % n;
}
putchar('\n');
return 0;
Re: Po drátě 3: Řešení úlohy č. 12 shichman (3. 12. 2008 - 22:10) Sbalit(1)
Přiznám se, programování mi jde jako psovi pastva. Zíráním do kódu jsem nezjistil zhola ničeho a pomalu se propadal do zoufalství - konec těsně před cílem zabolí, viďte. Bezcílné škádlení gdb, ehm, tedy ddd, mě do extáze také nepřivedlo. Pomohl mi až selský rozum: jeden vhodně umístěný printf mi po rekompilaci osvětlil, že výběr znaků ze vstupního řetězce odpovídá povědomé řadě. Tedy pro prvních pár indexů. Dojít ke vzorci 2^N mod 101 už byla otázka chvilky.
Okamžik pravdy ... místo v C jsem vsadil na osvědčený awk.
awk '{ for (i = 0; i < length($0) - 1; i++) printf "%s", substr($0, ((2^i)% length($0)), 1) }'