Matematické Fórum

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

#1 18. 11. 2013 22:55

ho77a
Zelenáč
Příspěvky: 19
Reputace:   
 

pascal pomocí polí rozdíl dní v kalendáři

Na vstupu je zadáno šest celých čísel, která představují dvě kalendářní data ve tvaru
Den1  Mesic1  Rok1
Den2  Mesic2  Rok2
Obě data jsou korektní, první z nich je v kalendáři dříve než druhé (tzn. je starší). Určete počet dní, který uplynul nebo uplyne mezi oběma daty. Při výpočtu počítejte s přestupnými roky. Výsledný počet dní se nemusí vejít do proměnné typu integer, použijte typ longint. Hodnotí se nejen správnost výsledků, ale i efektivita zvoleného postupu řešení.

Příklady:
- pro vstup  3  3  2011  5  3  2011  bude správným výsledkem číslo 2
- pro vstup  15  1  2000  15  1  2001  bude správným výsledkem číslo 366
- pro vstup   1  1  2000  1  1  2010  bude správným výsledkem číslo 3653

Offline

 

#2 19. 11. 2013 20:57

Formol
Místo: Praha
Příspěvky: 782
Pozice: krotitel mikroskopů (UHIEM 1. LF UK)
Reputace:   42 
 

Re: pascal pomocí polí rozdíl dní v kalendáři

↑ ho77a:
Jednoduché odečítání, které komplikuje jen výskyt přestupných roků. Pro určení přestupného roku je celkem jednoduché pravidlo: Rok je přestupný, pokud je dělitelný 4 a není dělitelný 100 nebo pokud je dělitelný 400.

Myslím, že i zde se vztahuje pravidlo řešení příkladů, tedy měl bys zkusit napsat, k čemu jsi sám došel.


Доктор сказал «в морг» — значит в морг!

Offline

 

#3 19. 11. 2013 21:30

ho77a
Zelenáč
Příspěvky: 19
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

ten přestupný rok by mohl být takhle aspon myslím

function Prestupny (Rok: integer): boolean;

begin
Prestupny := (Rok mod 4 = 0) and (Rok mod 100 <> 0)
or (Rok mod 400 = 0)
end;

ale dál fakt nevím

Offline

 

#4 19. 11. 2013 21:47

Formol
Místo: Praha
Příspěvky: 782
Pozice: krotitel mikroskopů (UHIEM 1. LF UK)
Reputace:   42 
 

Re: pascal pomocí polí rozdíl dní v kalendáři

↑ ho77a:

(k té funkci - vřele doporučuji nešetřit závorkami)

První nápad:

1. Spočítej si, kolik celých let je mezi zadanými roky, tedy nepočítej "krajní". Např. mezi lety 1840 a 1845 jsou takové roky 4. Tedy vezmeš 365*4. Dále si tyto roky projdi a zjisti, který z nich je přestupný (prostor pro optimalizaci - skutečně je třeba procházet všechny roky?). (Další prostor pro časovou optimalizaci - je skutečně efektivní zadávat jednoduchou podmínku jako funkci? Ta režie s tím spojená...)

2. Spočítej si, kolik ti z prvního roku chybí dní do konce roku. Například můžeš mít v poli 12 integerů počet dní v měsíci. (prostor pro časovou optimalizaci - nedalo by se použít pole s 11 prvky, kde by bylo na 1. místě počet dní bez ledna, na druhém počet dní bez ledna a února,...). No a pokud máš zadaný leden nebo únor a je přestupný rok, přidej jeden den.

3. Spočítej si, kolik dní z posledního roku chybí do konce roku. Finta podobná jako bod 2.

4. Všechno sečti.


Доктор сказал «в морг» — значит в морг!

Offline

 

#5 19. 11. 2013 21:49

ho77a
Zelenáč
Příspěvky: 19
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

jj tedka jenom ten největší problem vymyslet to v pascalu který vidím poprví

Offline

 

#6 19. 11. 2013 22:05

Formol
Místo: Praha
Příspěvky: 782
Pozice: krotitel mikroskopů (UHIEM 1. LF UK)
Reputace:   42 
 

Re: pascal pomocí polí rozdíl dní v kalendáři

↑ ho77a:
Tak s tím ti můžu poradit jen sednout k počítači a začít s "Hello, world!";-)


Доктор сказал «в морг» — значит в морг!

Offline

 

#7 19. 11. 2013 22:12

ho77a
Zelenáč
Příspěvky: 19
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

tak to naštěstí to Hello, world! umím :D ale je to to nejmenší

Offline

 

#8 20. 11. 2013 09:15 — Editoval Honzc (20. 11. 2013 09:16)

Honzc
Příspěvky: 4641
Reputace:   248 
 

Re: pascal pomocí polí rozdíl dní v kalendáři

↑ ho77a:
To že vidíš Pascal poprvé asi nebude tak moc pravda viz. 13.11. #12

Offline

 

#9 20. 11. 2013 12:29

ho77a
Zelenáč
Příspěvky: 19
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

promin tak po druhý já v tom stejně nevisím moc velký rozdíl

Offline

 

#10 20. 11. 2013 12:31

ho77a
Zelenáč
Příspěvky: 19
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

Program dnipocet (vstup, výstup);
používá
    crt;
const
      mesic: array [1. .. 12] celé číslo =
             (31,29,31,30,31,30,31,31,30,31,30,31);
var
   rokpoc, mespoc, denpoc, rokkon, Meskon, denkon: integer;
   pocdnu: real;
   r1, r2, r, konec: string;
   i: integer;
begin
write ('Pocatecni rok =');
     readln (rokpoc);
     write ('Pocatecni mesic =');
     readln (mespoc);
write ('Pocatecni den =');
     readln (denpoc);
     r2: = 'n';
     pokud rokpoc / 4 = int (rokpoc / 4), pak r2: = 'a';
     pokud rokpoc/100 = int (rokpoc/100), pak r2: = 'n';
     pokud rokpoc/400 = int (rokpoc/400), pak r2: = 'a';
     if ((denpoc = 29) a (mespoc = 2) a (r2 = 'n')), pak
        začít
          writeln ('MŘsc m Jen 28 dn');
          goto 3;
        end;
ale dál nevím
tedy aspon zatím nevím

Offline

 

#11 20. 11. 2013 13:51 — Editoval Honzc (20. 11. 2013 13:54)

Honzc
Příspěvky: 4641
Reputace:   248 
 

Re: pascal pomocí polí rozdíl dní v kalendáři

↑ ho77a:
To bys ale už mohl zvládnout napsat program, který načte oba datumy a třeba je vypíše na obrazovku. Zatím se nic nepočítá.
Pro inspiraci třeba

Offline

 

#12 20. 11. 2013 13:54 — Editoval Formol (20. 11. 2013 14:02)

Formol
Místo: Praha
Příspěvky: 782
Pozice: krotitel mikroskopů (UHIEM 1. LF UK)
Reputace:   42 
 

Re: pascal pomocí polí rozdíl dní v kalendáři

↑ ho77a:
Tak tudy nejspíš ne, protože nevím, co chceš vůbec sdělit (zejm. to goto? kam? a obecně v Pascalu je goto fuj!). Napíšu ti v náznaku funkce na hrubou a neověřenou implementaci mého postupu:

Výpočet celých let:

Code:

function celeRoky(r1,r2:integer):longint;
var
  r,i,j:integer;  
  d:longint;
begin
  r:=r2-r1-1; /*počet celých let*/
  if r>=1 then /*pokud je více než jeden rok mezi intervaly*/
  begin
    d:=365*r; /*počet dní za předpokladu, že jde o nepřestupné roky*/
    /*nejprve příčtu všechny rodky dělitelné čtyřkou */
    i:=4 - ((r1+1) mod 4); /*kdy bude první dělitelný čtyřkou*/
    if r>=i then /*pokud se vejdeme do intervalu*/
    begin
      j:= (r-i) div 4; /*počet roků dělitelných čtyřmi*/
      d:=d+j;
    end;
    /*--------*/
    /*zcela stejným postupem odečteš roky dělitelné 100 a přičteš roky dělitelné 400*/
    /*důkladně si rozmysli, proč*/

  end
  else begin
    if r<=0 then d:=0; /*pokud jsou stejné nebo sousedící, není mezi nimi jeden celý rok*/
    if r=1 then  /*pokud je mezi roky jeden celý rok*/
    begin
       r:=r1+1; /*číslo toho roku*/
       if ((r mod 4)=0) and ((r mod 100)<>0)) or ((r mod 400) = 0) then d:=366 
       else d:=365;
    end;
  end;
  celeRoky:=d;
end;

Podobně počítání dní do konce daného roku je jednoduché, pokud využiješ např. předpočítané pole dnů v měsíci bez zadaného:

Code:

const DnyDoKonce:array[1..12] of integer = {365,365-31,365-31-28......,31};
/*prostě pole dní daného měsíce plus dalších měsíců do konce roku*/
.....
function doKonceRoku(d,m,r:integer):integer;
var
  a:integer;
begin
  a:=DnyDoKonce[m] - d; /*počet dní do konce roku v ideálním případě - den vlastně říká, kolik dní už uplynulo*/
  if jePrestupny(r) and ((m=1) or (m=2)) then a:=a+1; 
/*v lednu i v únoru v přestupném roce zbývá do konce roku o den víc. Rozmysli se, jak to bude s 29.2.*/
  doKonceRoku:=a;
end;

Výpočet dní od začátku roku do daného data je zcela analogický. (pokud není něco syntakticky v pořádku, tak se omlouvám, ale Pascal jsem už dlouho nepoužíval...)


Доктор сказал «в морг» — значит в морг!

Offline

 

#13 20. 11. 2013 22:41

ho77a
Zelenáč
Příspěvky: 19
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

proč to goto je fuj v pascalu?

Offline

 

#14 20. 11. 2013 22:51

ho77a
Zelenáč
Příspěvky: 19
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

například takhle pomocí toho goto jsem myslel
program dnipocet (input,output);
uses
    crt;
const
      mesic:array[1..12] of integer =
             (31,29,31,30,31,30,31,31,30,31,30,31);
label
     1,2,3,4;
var
   rokpoc,mespoc,denpoc,rokkon,meskon,denkon:integer;
   pocdnu:real;
   r1,r2,r,konec:string;
   i:integer;

   begin
2:   clrscr;
     write('Pocatecni rok = ');
     readln(rokpoc);
     write('Pocatecni mesic = ');
     readln(mespoc);
3:   write('Pocatecni den = ');
     readln(denpoc);
     r2:='n';
     if rokpoc/4=int(rokpoc/4) then r2:='a';
     if rokpoc/100=int(rokpoc/100) then r2:='n';
     if rokpoc/400=int(rokpoc/400) then r2:='a';
     if ((denpoc=29) and (mespoc=2) and (r2='n')) then
        begin
          writeln('MŘsˇc m  jen 28 dnˇ');
          goto 3;
        end;
     writeln;
     write('Konecny rok = ');
     readln(rokkon);
     write('Konecny mesic = ');
     readln(meskon);
4:   write('Konecny den = ');
     readln(denkon);
     r2:='n';
     if rokkon/4=int(rokkon/4) then r2:='a';
     if rokkon/100=int(rokkon/100) then r2:='n';
     if rokkon/400=int(rokkon/400) then r2:='a';
     if (denkon=29) and (meskon=2) and (r2='n') then
        begin
          writeln('MŘsˇc m  jen 28 dnˇ');
          goto 4;
        end;
     pocdnu:=0;
     if (rokkon=rokpoc) and (mespoc=meskon) then
        begin
          pocdnu:=pocdnu+(denkon-denpoc+1);
          goto 1;
        end;
     if rokkon=rokpoc then
        begin
          for i:=mespoc+1 to meskon-1 do
              begin
                pocdnu:=pocdnu+mesic[i];
                if i=2 then
                   begin
                     r1:='n';
                     if rokpoc/4=int(rokpoc/4) then r1:='a';
                     if rokpoc/100=int(rokpoc/100) then r1:='n';
                     if rokpoc/400=int(rokpoc/400) then r1:='a';
                     if r1='n' then pocdnu:=pocdnu-1;
                 end;
              end;
        end;
     if rokpoc<rokkon then
        begin
          for i:=mespoc+1 to 12 do
              begin
                pocdnu:=pocdnu+mesic[i];
                if i=2 then
                   begin
                     r1:='n';
                     if rokpoc/4=int(rokpoc/4) then r1:='a';
                     if rokpoc/100=int(rokpoc/100) then r1:='n';
                     if rokpoc/400=int(rokpoc/400) then r1:='a';
                     if r1='n' then pocdnu:=pocdnu-1;
                   end;
              end;
          for i:=1 to meskon-1 do
              begin
                pocdnu:=pocdnu+mesic[i];
                if i=2 then
                   begin
                     r1:='n';
                     if rokkon/4=int(rokkon/4) then r1:='a';
                     if rokkon/100=int(rokkon/100) then r1:='n';
                     if rokkon/400=int(rokkon/400) then r1:='a';
                     if r1='n' then pocdnu:=pocdnu-1;
                   end;
              end;
        end;
     if rokkon-rokpoc>=2 then
        begin
          for i:=rokpoc+1 to rokkon-1 do
              begin
                r1:='n';
                if i/4=int(i/4) then r1:='a';
                if i/100=int(i/100) then r1:='n';
                if i/400=int(i/400) then r1:='a';
                if r1='n' then pocdnu:=pocdnu+365;
                if r1='a' then pocdnu:=pocdnu+366;
              end;
        end;
     pocdnu:=pocdnu+(mesic[mespoc]-denpoc+1);
     r1:='n';
     if rokpoc/4=int(rokpoc/4) then r1:='a';
     if rokpoc/100=int(rokpoc/100) then r1:='n';
     if rokpoc/400=int(rokpoc/400) then r1:='a';
     if (r1='n') and (mespoc=2) then pocdnu:=pocdnu-1;
     pocdnu:=pocdnu+denkon;
1:   writeln;
     writeln('Pocet dnu = ',pocdnu:18:0);
     write('Konec (a/n) ');
     readln(konec);
     if konec = 'n' then goto 2;
   end.

Offline

 

#15 20. 11. 2013 22:52

ho77a
Zelenáč
Příspěvky: 19
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

toje u mě jediná možnost jiná asi ne bohužel
ale asi to nebudou pomocí toho goto

Offline

 

#16 21. 11. 2013 07:53

Formol
Místo: Praha
Příspěvky: 782
Pozice: krotitel mikroskopů (UHIEM 1. LF UK)
Reputace:   42 
 

Re: pascal pomocí polí rozdíl dní v kalendáři

↑ ho77a:
Protože jde o konstukci mimo strukturované programování. To vedle koncepčí nečistoty a horší přehlednosti zdrojového kódu vede k tomu, že přeložený program je méně efektivní.

Prakticky všechno jde nahradit stejně přehledně cykly. Například tvůj cyklus kontroly korektně zadaného data by bylo mnohem lepší řešit cyklem repeat-until. No a protože to použiješ 2x, byla by na místě procedura.

Vlastní cyklus by vypadal nějak takhle (v pseudokódu):
repeat
  načti D,M,R
until (M in [1..12]) and ((D in [1..pocetDni[M]]) or (prestupny(M) and (D in [1..pocetDni[M]+1]));


Доктор сказал «в морг» — значит в морг!

Offline

 

#17 21. 11. 2013 09:09

Honzc
Příspěvky: 4641
Reputace:   248 
 

Re: pascal pomocí polí rozdíl dní v kalendáři

↑ Formol:
Pan kolega ↑ ho77a: totiž řeší něco jiného než musí (viz. zadání "..Obě data jsou korektní, první z nich je v kalendáři dříve než druhé.."), ale to co má vyřešit, tak mu nejde ani v nějakém smysluplném náznaku.

Offline

 

#18 21. 11. 2013 12:05

Formol
Místo: Praha
Příspěvky: 782
Pozice: krotitel mikroskopů (UHIEM 1. LF UK)
Reputace:   42 
 

Re: pascal pomocí polí rozdíl dní v kalendáři

↑ Honzc:
Také jsem si všiml:-) Tohle jsem doplnil jen jako ilustraci toho, že goto skutečně není pro většinu konstrukcí třeba (ale když jsem kdysi přecházel z ATARI BASICu, tak mi citelně chyběly konstrukce ON A GOTO a GOTO A). Byl bych prostě špatný učitel, nechávám se snadno "odlákat" od řešeného problému k tomu, co student také neumí...


Доктор сказал «в морг» — значит в морг!

Offline

 

#19 21. 11. 2013 17:42

Wrunx
Příspěvky: 65
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

no, tak jsem mrknul na net, popadnul jsem první vzořeček co se mi dostal pod ruku, a tady je nástřel výpočtu. pro uvedené tři případy v zadání funguje, aktuální juliánské datum podle netu taky souhlasí, jestli je to ale košer pro kdejaké datumy, jsem nezkoumal :-)
jak na to přes pole, nevím, ale třeba aspoň tohle bude k něčemu užitečné.

program julian;

var ju1,ju2:real;

function juli(d,m,r:integer):real;
const difka=1721118.5;
var i,f,g:real;
begin
  if m<3 then
  begin
    f:=m+12; g:=r-1;
  end;
  if m>=3 then
  begin
    f:=m; g:=r;
  end;
  i:=d+int((153*f-457)/5);
  i:=i+365*g+int(g/4)-int(g/100)+int(g/400)+difka;
  juli:=i;
end;

begin
ju1:=juli(3,3,2011);
ju2:=juli(5,3,2011);
writeln(ju2-ju1);
end.

Offline

 

#20 24. 02. 2016 17:28

pierres
Zelenáč
Příspěvky: 1
Škola: MFF UK
Pozice: byvaly student
Reputace:   
 

Re: pascal pomocí polí rozdíl dní v kalendáři

Tak kdysi jsem to mel u zkousky, kde jsem se zamotal v podminkach, tady to je pres 2 funkce a funguje to je tam osetrena podminka, kdyz je prestupny rok a je zadan 1. nebo druhy mesic, aby to nepocitalo den navic. Pokud jde o nacitani pres pole je to zalezitost pouze definici 1 nebo 2 poli a trochu to poupravit. Snizi to pocet promennych.
__________________________________________________________________________

Code:

Program Rozdil Dnu;
uses crt;
var
y,d1,d2,m1,m2,r1,r2,pdm1,pdm2:integer;
z,pdr1,pdr2:longint;

function rok(var x,y:integer):longint;
  begin
  z:=x*365+x div 4-x div 100+x div 400;
  if y<3 then
    if x mod 4=0 then
      if x mod 100<>0 then
      z:=z-1;
  if y<3 then
    if x mod 400=0 then
    z:=z-1;
  end;

function mesic(var x:integer):integer;
  var
  i:integer;
  pocetdnu: array[1..11] of integer = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30);
  begin
  y:=0;
    if x>1 then
      for i:=1 to x-1 do
      y:=y+pocetdnu[i];
  end;

Begin
write('den1= ');
readln(d1);
write('mesic1= ');
readln(m1);
write('rok1= ');
readln(r1);
write('den2= ');
readln(d2);
write('mesic2= ');
readln(m2);
write('rok2= ');
readln(r2);
rok(r1,m1);
pdr1:=z;
rok(r2,m2);
pdr2:=z;
mesic(m1);
pdm1:=y;
mesic(m2);
pdm2:=y;
writeln('rozdil dnu je ',pdr2-pdr1+pdm2-pdm1+d2-d1);
readln;
End.

_____________________________________________________________________________

Offline

 

Zápatí

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson