SCITANí Velkých, řídkých MATIC(Pascal),(uz nic, uz to mam :)

Programovacie jazyky, rady, poradňa...
ivetas
Novice
Novice
Používateľov profilový obrázok
Príspevky: 3
Registrovaný: 19 mar 2010, 22:51

SCITANí Velkých, řídkých MATIC(Pascal),(uz nic, uz to mam :)

Príspevok od používateľa ivetas »

Ahojte ludia, mam tu jeden program na spojove zoznamy. Za 3 dni bol moj maximalny vykon,ze som to skompilovala. So spojakmi som sa zoznamila pred 2 tyzdnami, takze bohuzial su moje vedomosti zatial nic moc. Prosim niekoho skusenejsieho programatora, keby nato mal trpezlivost a presiel by moj program v pripade mi poradil kde robim chybu, bola by som velmi rada. Do pondelka to mam poslat do CODEXU (univerzitny server na testovanie programov). Bola by to skoda keby som po tolkej namahe dostala 0%.
Takze zadanie:
Ve vstupním textovém souboru sparse.in je posloupnost čtvercových matic celých čísel. Všechny matice mají rozměr 1000000x1000000.

Každá matice je určena takto: První řádek ve vstupním souboru pro danou matici začíná znakem '#', za kterým následuje pořadové číslo matice. Pak následuje blíže neurčený počet řádků, které obsahují všechny nenulové prvky matice. Každý z těchto řádků začíná mezerou (nebo tabelátorem), a pak následují tři celá čísla (řádek, sloupec, hodnota) oddelená mezerami. Každý z těchto řádků tedy reprezentuje jeden nenulový prvek matice. Zadání každé matice končí řádkem, který začíná znakem '#'. Poté může následovat další matice. Vstupní posloupnost matic je ukončena řádkem, který začíná znakem '@'.

Úkolem je vypočítat součet zadaných matic a výsledek zapsat do výstupního textového souboru sparse.out. Pokud je však nějaká matice obsažena ve vstupních datech vícekrát, do výsledného součtu se započítá pouze jednou!

Formát výstupního textového souboru bude podobný jako formát vstupních dat. Výstupní soubor bude obsahovat tolik řádků, kolik bude nenulových prvků výsledného součtu matic. Na každém řádku budou tři celá čísla (řádek, sloupec, hodnota) oddělená mezerami analogicky jako ve vstupním souboru.
[/color]
Prvky jednotlivých matic nemusí být ani ve vstupním, ani ve výstupním souboru nijak uspořádány.

Následující příklad obsahuje deset matic ve vstupním souboru, ale do výsledného součtu se započítá pouze osm z nich, protože matice s pořadovým číslem #1 a #3 jsou totožné (tudíž se do součtu započítá pouze jedna z nich), podobně také matice #5 a #9. Matice #8 obsahuje samé nuly.

Příklad vstupu:
#1
1 1 1
2 2 2
1000000 1000000 1000000
1 100 100
2 100 100
3 100 99
#
#2
1 1 1
2 2 2
1000000 1000000 1000000
1 100 100
2 100 100
3 100 100
#
#3
1 1 1
2 2 2
1000000 1000000 1000000
1 100 100
2 100 100
3 100 99
#
#4
100 100 1
#
#5
100 100 2
#
#6
100 100 3
#
#7
100 100 4
#
#8
#
#9
100 100 2
#
#10
100 100 5
#
@

Správný výstup:
1 1 2
1 100 200
2 2 4
2 100 200
3 100 199
100 100 15
1000000 1000000 2000000
MOJ PROGRAM:

Kód: Vybrať všetko

program ridke_matice;

type spoj=^seznam;
     seznam=record
                  radek:longint;
                  sloupec:longint;
                  hod:longint;
                  dalsi:spoj;
                  dolu:spoj;
                  end;

var start:spoj;
    prvni:spoj;
    ins,kam:text;
    slovo, tslovo:string;
    x,y,value,i:longint;
    code: integer;

procedure PrevedNaTriCisla (s: string; var x,y,value :longint);
var i,code:integer;
    temp:string;

begin
  i:=0;
  x:=-1; y:=-1;
  temp:='';

  repeat
        i:=i+1;

        if((temp <> '') and (s[i] = ' ')) then
                begin
                        if(x=-1) then
                                val(temp, x, code);
                        if(y=-1) then
                                val(temp, y, code);

                        temp:='';
                end
        else
                if(s[i] <> ' ') then
                        temp:=temp + s[i];

  until (i=Length(s));

  val(temp, value, code);
end;

procedure  pripoj (dalsiradek:boolean;var zacatekmatice:spoj;x,y,value:longint);
{dalsiradek mi urci ci ma pripojit krabicku na dalsi riadok alebo pokr v matici na zacatek matice}
var kam,last,zacatekradku:spoj;
begin
     last:=nil; zacatekradku:=nil;kam:=nil;

     if (zacatekmatice <> nil) then
                        begin
                             zacatekradku:=zacatekmatice;
                             {zac.rad je ukazatel na zacatek posledniho radku}
                             while (zacatekradku^.dolu <>nil) do zacatekradku:=zacatekradku^.dolu;

                             last:=zacatekradku;
                             {last je ukazatel na posledny prvok posledneho radku}

                             while (last^.dalsi<>nil) do last:=last^.dalsi;
                        end
     else
         last:=nil;

     new (kam);
     kam^.radek:=x;
     kam^.sloupec:=y;
     kam^.hod:=value;
     kam^.dalsi:=nil;
     kam^.dolu:=nil;

     if (last <>nil) then
              begin
                   if (dalsiradek) then
                      zacatekradku^.dolu:=kam {pridam ako novy riadok}
                   else
                       last^.dalsi:=kam; {pridam na konec}
              end;

     if (zacatekmatice=nil) then zacatekmatice:=kam;
     if (start=nil) then start:=kam;
      {start nastavim na prvy prvok prvej matice}
end;

procedure secti (var zaciatok:spoj);
var i,j,k:longint;
    prvok:spoj;
    last,zac,pom,pocet,index:spoj;

begin
     prvok:=zaciatok;
     zac:=zaciatok^.dolu;
     pom:=zaciatok^.dolu;
     index:=zaciatok^.dolu;

                         pocet:=zaciatok;
                         i:=0;
                         while pocet<>nil do begin
                                             inc (i);
                                             pocet:=pocet^.dolu;
                                             end;
                         last:=zaciatok;

                         for j:=1 to (i-1) do last:=last^.dolu;

 repeat

  while prvok<>nil do begin
     while zac<>nil do begin
                            while (prvok^.radek<>pom^.radek) and
                                  (prvok^.sloupec<>pom^.sloupec) and
                                  (pom<>nil) do
                                    pom:= pom^.dalsi;

                            if pom=nil {dosli sme sa na konec} then
                               begin
                               zac:=zac^.dolu;
                               pom:=zac;
                               end

                            else begin
                                 prvok^.hod:=(prvok^.hod)+(pom^.hod);
                                 pom^.radek:=-1;
                                 pom^.sloupec:=-1;
                                 zac:=zac^.dolu;
                                 pom:=zac;
                                 end;
                          end;
  prvok:=prvok^.dalsi;
  zac:=index;
                        end;
                   prvok:=index;
                   index:=index^.dolu;
                   zac:=index;

  until prvok=last;
 end;

procedure spojenie (var zaciatok:spoj);
var i,j:integer;
    pom,zac,ukaz:spoj;

begin
     zac:=zaciatok;
     pom:=zac;
     ukaz:=zac^.dolu;

     while (ukaz<>nil) do
           begin
                while (pom<>nil) do pom:=pom^.dalsi;
                pom:=ukaz;
                zac^.dolu:=nil;
                zac:=ukaz;
                ukaz:=ukaz^.dolu;
           end;
end;


procedure porovnaj (var zaciatok:spoj);
var pom1,pom2,chod,zac1,zac2,ukaz1,ukaz2:spoj;
    i,j,k:integer;
begin
     pom1:=zaciatok;
     pom2:=zaciatok^.dolu;
     zac1:=pom1;
     zac2:=pom2;
     chod:=pom2;
     ukaz1:=pom1;
     ukaz2:=pom2;


  while ukaz1<>nil do begin
     while ukaz2<>nil do begin
                                 i:=0;
                                 j:=0;
                                 pom1:=ukaz1;
                                 pom2:=ukaz2;

                                 while pom1^.dalsi<>nil do
                                       begin
                                       pom1:= pom1^.dalsi;
         {zistim zda jsou velikosti }  inc(i);
         {matic rovnake tj.i=j}        end;


                                 while pom2^.dalsi<>nil do
                                       begin
                                       pom2:=pom2^.dalsi;
                                       inc (j);
                                       end;

                                if i=j then {potrebujem porovnat prvky}
                                        begin{je tu moznost ze sa budu rovnat}
                                        k:=0;
                                            zac1:=ukaz1;
                                            zac2:=ukaz2;
                                            chod:=ukaz2;

                                            while  (zac1^.radek=zac2^.radek) and
                                                   (zac1^.sloupec=zac2^.sloupec) and
                                                   (zac1^.hod=zac2^.hod) do
                                                   inc (k); {pocitaj kolko hodnot sa rovna}
                                         if k=i then {oni sa rovnaju}
                                                begin
                                                     while chod<>nil do
                                                           begin
                                                           chod^.hod:=0;
                                                           chod:=chod^.dalsi;
                                                           end;

                                                  end;

                                 ukaz2:=ukaz2^.dolu;

                                    end;
                           ukaz1:=ukaz1^.dolu;
                           ukaz2:=ukaz1^.dolu;
                                   end;
   end;

 end;

procedure vypis (var zaciatok:spoj);
var chod:spoj;
begin
     chod:=zaciatok;

     while (chod<>nil) do begin
                               if (chod^.radek<>-1) then
                                  begin
                                   writeln (kam,chod^.radek,' ',chod^.sloupec,' ',chod^.hod);
                                   chod:=chod^.dalsi;
                                  end
                               else
                                   chod:=chod^.dalsi;
                           end;


end;

begin

     start := nil;
     prvni := nil;

     assign (ins,'sparse.in');
     assign (kam,'sparse.out');
     reset (ins);
     rewrite (kam);

     repeat
          readln(ins, slovo);
          if (slovo[1]='#') then
             begin
                  i:=0;
                  repeat
                         readln(ins, tslovo);

                         if(tslovo<>'#') then
                           begin
                              i:= i + 1;

                              prevednatricisla  (tslovo,x,y,value);

                               if(i=1) then
                                Pripoj (true, prvni, x, y, value) {novy radek}
                              else
                                Pripoj (false, prvni, x, y, value); {pridej na konec}
                           end;
                  until (tslovo='#');
             end;
     until (slovo='@');

     close(ins);
     prvni:=start;
     porovnaj (start);
     secti (start);
     spojenie (start);
     Vypis (start);
     close (kam);

end.
//autoeditácia príspevku (19 Mar 2010, 23:17)
keby to niekomu pomohlo:
Záznam o vyhodnocení
Compiling... OK
Test 1... <init> <run> RE:Runtime error 201: Range check error
Test 2... <init> <run> RE:Runtime error 201: Range check error
Test 3... <init> <run> RE:Runtime error 201: Range check error :)
chrono
VIP
VIP
Používateľov profilový obrázok
Príspevky: 7127
Registrovaný: 25 dec 2006, 15:17

Re: POMOZTE MI PROSIM: SCITANí Velkých, řídkých MATIC (Pascal)

Príspevok od používateľa chrono »

Veľa miest, kde by mohla táto chyba nastať tam nevidím (ak si dobre pamätám, tak sa týka práci s poliami). Čiže skús tam dať nejaké pomocné výpisy okolo miest, kde sa pracuje s poľom (teda jednoduchšie je asi skompilovať a spustiť to tak, aby to zastalo priamo na tom problémovom riadku, ale netuším aký pascal používaš).

Skús dať napr. výpis za to readln(ins, slovo); (aby bolo jasné, či sa do tej premennej niečo načítalo, inak nasledujúci riadok spôsobí práve takú chybu).
ivetas
Novice
Novice
Používateľov profilový obrázok
Príspevky: 3
Registrovaný: 19 mar 2010, 22:51

Re: POMOZTE MI PROSIM: SCITANí Velkých, řídkých MATIC (Pascal)

Príspevok od používateľa ivetas »

:))))...konecne sa niekto ozval...:)))...chybu range check error , sa mi podarilo opravit, teraz mi hlasi chyby:
Compiling... OK
Test 1... <init> <run> TO:Time limit exceeded
Test 2... <init> <run> TO:Time limit exceeded
Test 3... <init> <run> TO:Time limit exceeded

sa snazim zatial nejak prepisat procedury "porovnaj" a "vypis", bohuzial este stale je to pomale
uz mi ten program pekne lezie na nervy...:/
pouzivam Borland Turbo Pascal 7.0
zatial mam :

Kód: Vybrať všetko

program ridke_matice;

type spoj=^seznam;
     seznam=record
                  radek:longint;
                  sloupec:longint;
                  hod:longint;
                  dalsi:spoj;
                  dolu:spoj;
                  end;

var start:spoj;
    prvni:spoj;
    ins,kam:text;
    slovo, tslovo:string;
    x,y,value,i:longint;
    code: integer;

procedure PrevedNaTriCisla (s: string; var x,y,value :longint);
var i:longint;code:integer;
    temp:string;

begin
  i:=0;
  x:=-1; y:=-1;
  temp:='';

  repeat
        i:=i+1;

        if((temp <> '') and (s[i] = ' ')) then
                begin
                        if(x=-1) then
                                val(temp, x, code);
                        if(y=-1) then
                                val(temp, y, code);

                        temp:='';
                end
        else
                if(s[i] <> ' ') then
                        temp:=temp + s[i];

  until (i=Length(s));

  val(temp, value, code);
end;

procedure  pripoj (dalsiradek:boolean;var zacatekmatice:spoj;x,y,value:longint);
{dalsiradek mi urci ci ma pripojit krabicku na dalsi riadok alebo pokr v matici na zacatek matice}
var kam,last,zacatekradku:spoj;
begin
     last:=nil; zacatekradku:=nil;kam:=nil;

     if (zacatekmatice <> nil) then
                        begin
                             zacatekradku:=zacatekmatice;
                             {zac.rad je ukazatel na zacatek posledniho radku}
                             while (zacatekradku^.dolu <>nil) do zacatekradku:=zacatekradku^.dolu;

                             last:=zacatekradku;
                             {last je ukazatel na posledny prvok posledneho radku}

                             while (last^.dalsi<>nil) do last:=last^.dalsi;
                        end
     else
         last:=nil;

     new (kam);
     kam^.radek:=x;
     kam^.sloupec:=y;
     kam^.hod:=value;
     kam^.dalsi:=nil;
     kam^.dolu:=nil;

     if (last <>nil) then
              begin
                   if (dalsiradek) then
                      zacatekradku^.dolu:=kam {pridam ako novy riadok}
                   else
                       last^.dalsi:=kam; {pridam na konec}
              end;

     if (zacatekmatice=nil) then zacatekmatice:=kam;
     if (start=nil) then start:=kam;
      {start nastavim na prvy prvok prvej matice}
end;

procedure secti (var zaciatok:spoj);
var i,j,k:longint;
    prvok:spoj;
    zac,pom,index:spoj;

begin
     prvok:=zaciatok;
     zac:=zaciatok^.dolu;
     pom:=zaciatok^.dolu;
     index:=zaciatok^.dolu;

                        { pocet:=zaciatok;
                         i:=0;
                         while pocet<>nil do begin
                                             inc (i);
                                             pocet:=pocet^.dolu;
                                             end;
                         last:=zaciatok;

                         for j:=1 to (i-1) do last:=last^.dolu;}

 repeat

  while prvok<>nil do begin
     while zac<>nil do begin
                            while (prvok^.radek<>pom^.radek) and
                                  (prvok^.sloupec<>pom^.sloupec) and
                                  (pom<>nil) do
                                    pom:= pom^.dalsi;

                            if pom=nil {dosli sme sa na konec} then
                               begin
                               zac:=zac^.dolu;
                               pom:=zac;
                               end

                            else begin
                                 prvok^.hod:=(prvok^.hod)+(pom^.hod);
                                 pom^.radek:=-1;
                                 pom^.sloupec:=-1;
                                 zac:=zac^.dolu;
                                 pom:=zac;
                                 end;
                          end;
  prvok:=prvok^.dalsi;
  zac:=index;
                        end;
                   prvok:=index;
                   index:=index^.dolu;
                   zac:=index;

  until index=nil;
 end;

procedure spojenie (var zaciatok:spoj);
var i,j:longint;
    pom,zac,ukaz:spoj;

begin
     zac:=zaciatok;
     pom:=zac;
     ukaz:=zac^.dolu;

     while (ukaz<>nil) do
           begin
                while (pom<>nil) do pom:=pom^.dalsi;
                pom:=ukaz;
                zac^.dolu:=nil;
                zac:=ukaz;
                ukaz:=ukaz^.dolu;
           end;
end;


procedure porovnaj (var zaciatok:spoj);
var pom1,pom2,chod,zac1,zac2,ukaz1,ukaz2,maz:spoj;
    i,j,k:longint;
begin
     pom1:=zaciatok;
     pom2:=zaciatok^.dolu;
     zac1:=pom1;
     zac2:=pom2;
     chod:=pom2;
     ukaz1:=pom1;
     ukaz2:=pom2;


  while ukaz1<>nil do begin
     while ukaz2<>nil do begin
                                 i:=0;
                                 j:=0;
                                 pom1:=ukaz1;
                                 pom2:=ukaz2;

                                 while pom1^.dalsi<>nil do
                                       begin
                                       pom1:= pom1^.dalsi;
         {zistim zda jsou velikosti }  inc(i);
         {matic rovnake tj.i=j}        end;


                                 while pom2^.dalsi<>nil do
                                       begin
                                       pom2:=pom2^.dalsi;
                                       inc (j);
                                       end;

                                if i=j then {potrebujem porovnat prvky}
                                        begin{je tu moznost ze sa budu rovnat}
                                        k:=0;
                                            zac1:=ukaz1;
                                            zac2:=ukaz2;
                                            chod:=ukaz2;

                                            while  (zac1^.radek=zac2^.radek) and
                                                   (zac1^.sloupec=zac2^.sloupec) and
                                                   (zac1^.hod=zac2^.hod) do
                                                   inc (k); {pocitaj kolko hodnot sa rovna}
                                         if k=i then {oni sa rovnaju}
                                                begin
                                                     zac1^.dolu:=zac2^.dolu; {prepojim sipku}
                                                     while chod<>nil do     {zmazem cely riadok}
                                                           begin
                                                           maz:=chod;
                                                           chod:=chod^.dalsi;
                                                           dispose (maz);
                                                           end;

                                                  end;

                                 ukaz2:=ukaz2^.dolu;

                                    end;
                           ukaz1:=ukaz1^.dolu;
                           ukaz2:=ukaz1^.dolu;
                                   end;

   end;

 end;

procedure vypis (var zaciatok:spoj);
var chod:spoj;
begin
     chod:=zaciatok;

     while (chod<>nil) do begin
                               if (chod^.radek<>-1) then
                                  begin
                                   writeln (kam,chod^.radek,' ',chod^.sloupec,' ',chod^.hod);
                                   chod:=chod^.dalsi;
                                  end
                               else
                                   chod:=chod^.dalsi;
                           end;


end;

begin

     start := nil;
     prvni := nil;

     assign (ins,'sparse.in');
     assign (kam,'sparse.out');
     reset (ins);
     rewrite (kam);

     repeat
          readln(ins, slovo);
          if (slovo[1]='#') then
             begin
                  i:=0;
                  repeat
                         readln(ins, tslovo);

                         if(tslovo<>'#') then
                           begin
                              i:= i + 1;

                              prevednatricisla  (tslovo,x,y,value);

                               if(i=1) then
                                Pripoj (true, prvni, x, y, value) {novy radek}
                              else
                                Pripoj (false, prvni, x, y, value); {pridej na konec}
                           end;
                  until (tslovo='#');
             end;
     until (slovo='@');

     close(ins);
     prvni:=start;
     porovnaj (start);
     secti (start);
     spojenie (start);


     Vypis (start);
     close (kam);

end.
chrono
VIP
VIP
Používateľov profilový obrázok
Príspevky: 7127
Registrovaný: 25 dec 2006, 15:17

Re: POMOZTE MI PROSIM: SCITANí Velkých, řídkých MATIC (Pascal)

Príspevok od používateľa chrono »

Pravdu povediac, príliš tomu nerozumiem. Máš tam načítať viac matíc a ty tam používaš nejakú fintu, pomocou ktorej to pridávaš do toho jedného zoznamu. Nebolo by prehladnejšie mať zoznam, v ktorom budú odkazy na samotné matice (a tie matice budú viac menej také zoznamy, ako tam máš teraz).

A ani netuším, ako (a kedy) tam zisťuješ, či je rovnaká matica už načítané uložená. Teda asi by to malo robiť niečo takéto (a možno to tam robíš, ale je to dosť neprehľadné): načítaš jednu maticu a potom ju postupne porovnáš so všetkými už načítanými; ak je iná, ako tie predtým, pridáme ju do zoznamu matíc a načítame ďalšiu...
Napísať odpoveď