Nevíte-li si rady s jakýmkoliv matematickým problémem, toto místo je pro vás jako dělané.
Nástěnka
❗22. 8. 2021 (L) Přecházíme zpět na doménu forum.matweb.cz!
❗04.11.2016 (Jel.) Čtete, prosím, před vložení dotazu, děkuji!
❗23.10.2013 (Jel.) Zkuste před zadáním dotazu použít některý z online-nástrojů, konzultovat použití můžete v sekci CAS.
Nejste přihlášen(a). Přihlásit
Zdravím,
dělám ročníkovou práci do programování.
Zadání: Je dán počet dětí, délka rozpočítadla a číslo dítěte, od kterého se začne počítat. Vypište čísla dětí, která postupně vypadávají.
Vše už prakticky funguje, lae zatím jsem dokonale nevyřešil to, jak přeskakovat již vyhozené děti, je tam sice cyklus while, ale nepřeskočí to na správné dítě, sice všechny děti vypadnou, ale pak už je ve správném pořadí.
Celý program je zde:
program ROZPOCITADLO;
type pole=array[1..100] of integer;
var vyp:pole;
poc, x, delka, i, zac, out, je:integer;
function hledej(out:integer; vyp:pole):boolean;
var fi, fje:integer;
begin
fje:=0;
for fi:=1 to x do
if vyp[fi]=out then fje:=fje+1;
if fje>0 then hledej:=true else hledej:=false;
end;
begin
x:=0;
writeln('--- Rozpocitadlo // Pavel Hodoval ---');
write('Zadej pocet deti: ');
readln(poc);
write('Zadej delku rozpocitadla: ');
readln(delka);
write('Od ktereho ditete se zacina? (1 az ', poc, '):');
readln(zac);
repeat
if (delka+zac-1)>poc then out:=abs(poc-delka-zac+1) else out:=delka+zac-1;
kroky:=out;
while hledej(out,vyp)=true do
begin
if (out+1)>=poc then out:=abs(poc-out-1) else out:=out+1;
end;
if hledej(out,vyp)=false then
begin
x :=x+1;
vyp[x]:=out;
end;
if (out+1)>=poc then zac:=abs(poc-out-1) else zac:=out+1;
until poc=x;
for i:=1 to x do writeln(vyp[i]);
readln;
end.Předem díky za rady.
Offline

↑ Pajah:
Nezkoumala jsem program, ale co tahle upravit počet dětí - odečíst vždy 1 (vypadnuté), potřeba nové proměnné pro počet již vypadnutých dětí a pak přičíst počet vypadnutých dětí k pořadí právě vypadnutého dítěte.
Je to můj návrh, třeba není nejlepší, ale já bych to asi řešila takto.
Offline
Ale to neřeší můj problém, můj algoritmus v podstatě funguje, ale od určitého počtu již vyřazuje děti ve špatném pořadí (resp. je to posunuté), protože jsem zatím nevymyslel, jak jednoduše přeskočit vyhozené děti, a pak správně počítat (musí se pořád brát v úvahu délka rozpočítadla).
Dejme tomu, že máme 9 dětí, délka rozpočítadla je 3 a začíná se od dítěte s číslem 2.
1 2 3 4 5 6 7 8 9
Vypadne 4., 7., 1., 5., a pak tedy máme 2 3 6 8 9, a korektně se má vynechat sedmé dítě, čili vypadne 9. (protože délka je3), ale program mi vyhodí osmé. Jeidné, co jsem vymyslel, je pomocí cyklu while přeskakovat vyhozené děti, ale přoád to neřeší problém toho, že to neodpovídá délce rozpočítadla.
Offline
Pajah napsal(a):
Dejme tomu, že máme 9 dětí, délka rozpočítadla je 3 a začíná se od dítěte s číslem 2.
1 2 3 4 5 6 7 8 9
Vypadne 4., 7., 1., 5., a pak tedy máme 2 3 6 8 9, a korektně se má vynechat sedmé dítě, čili vypadne 9. (protože délka je3), ale program mi vyhodí osmé. Jeidné, co jsem vymyslel, je pomocí cyklu while přeskakovat vyhozené děti, ale přoád to neřeší problém toho, že to neodpovídá délce rozpočítadla.
Jak mas to pole (pole=array[1..100] of integer;), tak pozice bunky ti bude odkazovat na cislo ditete a do hodnoty nacti vsude ze zacatku 1 a kdyz dite vyhodis, tak to zmen na 0 a v druhem pruchodu ignoruj vsechny bunky s nulovou hodnotou.
Tak jsem se na to koukl jeste jednou a ty do toho pole uz nacitas rovnou serazene decka.
Co treba to zkusit takhle:
Vytvorit si pole a[1],a[2]...a[pocet], ktere bude mit ve vsech bunkach hodnotu 0. Potom rozbehnes algoritmus na rozpocitavani a do kazdeho bunky vepises poradi. Pokud tvuj algoritmus narazi na bunku s hodnotou ruznou od 0, tak ji preskoci.
Potom jen na konci vytvorit vhodny algoritmus na tisk.
Offline
Tehn while cyklus skroo na začátku repeatu (while hledej(ou,tvyp)=true.... zajišťuje přeskočení všech (i víc za sebou) vyhozených dětí, ale jde o to, že to pak nevyhazuje správně. Prostě to korektně třeab z 6 přeskočí na 8, protože 7 je vyloučená, ale délka rozpočítadla je 3, čili to přeskočilo pouze o 2 kroky. A nenapadá mě jak dopočítávat zbylé kroky, které jsou ještě potřeba.
Offline
Pascal neumím, ale takhle to vypadá v Maximě (hotová funkce):
fRozpoc(L,n):=block([d,e,i,Z,k],
k: 0,
Z: [],
d: length(L),
e: d,
for i:1 thru e do (
k: mod(k+(n-1),d),
Z: append(Z,[L[k+1]]),
L: delete(L[k+1],L),
d: d-1,
print(d," - ",Z," - ",L)
), Z
)$Komentář k některým řádkům:
k: mod(k+(n-1),d)
k: je index v poli, pomocí funkce modulo se počítá následující index (k+(n-1)), (n-1) je tam proto, že další člen není o n pozic dále, ale pouze o (n-1) pozic, protože jeden žák "jde ven". Pozor, Pole L nemá konstantní délku d, ale vždy ubyde jeden žák!
Z: append(Z,[L[k+1]])
L je pole všech žáků (odsud je vybíráme)
L[k+1] je aktuálně vybraný žák (maxima má pole začínající od 1 takže [k+1], Pascal začíná od 0, takže v pascalu bude pouze index k)
Z je prázdné pole do kterého postupně přesouváme vybrané žáky (funkce append připojí položku na konec pole)
L: delete(L[k+1],L)
Tento řádek odstraní vybraného žáka z původního pole
d: d-1
vybráním žáka se nám délka pole zmenší (počet žáků ubyde), je nutné odpočítat 1, aby předcházející funkce modulo počítala správně.
print(d," - ",Z," - ",L)
pouze pro odladění, vypisuje každý krok počet zbývajících žáků, obsah pole nevybraných žáků (postupně ubývá) a obsah pole vybraných žáků (postupně přibývá).
Z je pole žáků které vrací funkce
[3,6,9,2,7,1,8,5,10,4]
To je výsledek pro 10 žáků pro výběr každý třetí.
Offline
↑ Stýv:
Na programu Maxima jsem popsal krok za krokem algoritmus který řeší daný problém. Myslím si, že člověk který zvládá Pascal, by jej do něj dokázal přepsat. Já osobně, kdyby mi někdo popsal krok za krokem algoritmus řešení nějaké úlohy, jsem jej schopen napsat v programovacím jazyku který znám.
Chtěl jsem pouze pomoct.
Omlouvám se.
Offline
↑ mák: problém je, že pole v pascalu mají pevnou dýlku a nejde takhle přidávat prvky na konec nebo odebírat odprostředka. proto mi tvůj algoritmus v maximě přijde celkem k ničemu. ale co já vim, třeba to autorovi pomůže
neber si to tak, já jsem poslední dobou asi moc kousavej
Offline
Asi by bylo nejlepší, kdybyste si můj program zkusili zkompilvoat, abyste pochopili můj problém. Ten program v Maximě mi orpavdu nepomžůže, takhle s iv Pascalu s poli hrát nemůžu, ale samozřejmě díky za snahu o pomoc. Jeidný můj problém je, jak vymyslet nějaký další algoritmus, kteřý zařídí, že se správně posune "ukazatel" tak, aby posunutí fungovalo správně. První kolo vyhazování je v pořádku, po druhém už to dělá špatné pořadí.
Offline
↑ Pajah:
Me to ani nezkompilovalo. Na 24. radku to haze chybu, ze nemuze nejit 'kroky'.
A kdyz se tak divam, tak s tou promennou potom nikde nepracujes, takze nechapu, proc ji tam mas.
Offline
↑ Pajah:
Tohle mi pracuje.
type Tpole=array[1..100] of Integer;
var naz,vyp: Tpole;
i,j,poc,delka,zac,zb,a: Integer;
procedure Napln(var s: Tpole; n: Integer);
var i: Integer;
begin
for i := 1 to n do
s[i] := i;
end;
begin
WriteLn('--------- Rozpocitadlo ----------');
Write('Zadej pocet deti: ');
ReadLn(poc);
Write('Zadej delku rozpocitadla: ');
ReadLn(delka);
Write('Od ktereho ditete se zacina? (1 az ', poc, '): ');
ReadLn(zac);
Napln(naz,poc);
i := zac;
j := 0;
a := 0;
zb := 1;
while zb<=poc do
begin
if naz[i]<>0 then
a := a+1;
if a=delka then
begin
j := j+1;
vyp[j] := naz[i];
naz[i] := 0;
a := 0;
zb := zb+1;
end;
i := i+1;
if i-1=poc then
i := 1;
end;
WriteLn;
WriteLn('Poradi vypadnutych deti');
for i := 1 to poc do
Write(vyp[i],' ');
WriteLn;
ReadLn;
end.
Offline
↑ Stýv: Já bych na (cyklickém) zřetězeném seznamu netrval, školské úlohy nemají problém v tom, že fungují jen v nějakých mezích. Přítomnost dítěte jde kódovat jednobitově, i tak by se paměť dala šetřit, ale o to jistě vůbec nejde. V listu bys zase při každém vyřadění musel dealokovat paměť, takže programátorsky de facto stejně náročné jako vyhodnocování naz[] u ↑ Honzc:.
Jsme na matematickém fóru. Nešla by najít funkce f() taková, abychom prostě mohli psát jen
FOR i FROM 1 TO pocet_deti DO PRINT(f(i, pocet_deti))
?
Offline
↑ Stýv:
No asi tak, že mu nedovolíš zadat větší číslo (a zároveň menší než 1, bavíme se o přirozených číslech) než máš "délku" (velikost) pole.
Tedy např pro délku 100.
Write('Zadej pocet deti: ');
ReadLn(poc);
if (m<1)or(m>100) then //Pokud zadame cislo mimo interval
repeat //tak to nedovolime
WriteLn('Pocet deti musi byt cele cislo z intervalu <1,100>');
WriteLn;
Write(Zadej pocet deti: ');
ReadLn(poc);
until (m>=1)and(m<=100);
Offline
↑ Stýv: ok. Těžko říct, co má úloha prověřit/naučit. Možná modulární aritmetiku.
Offline
↑ Stýv:
Já teda nevím, proč by se nemohlo použít pole.
Nevím jestli v čistém Pascalu existuje procedura SetLength(), pomocí které je možné zadat velikost pole až ze známé
hodnoty jeho délky, ale v Delphi určitě existuje. Existuje i pro konzolové aplikace psané v Delphi. Pochybuju, že dnes někdo píše programy pouze v čistém Pascalu.
Já jsem chtěl kolegovi pouze ukázat jak se dá vyřešit jeho problém a použil jsem již jím definovaných proměnných (a tedy i pole dané fixní délky). Neřešil jsem tedy zda použít to nebo ono. Jak ty víš co jim ve škole řekli, že se má použít.
Offline