4 / 69
May 2017

Witam !
SPOJ nie akceptuje mi mojego kodu, który lokalnie (Code Blocks) działa dobrze. Według SPOJ-a jest błąd:

błąd wykonania (SIGABRT)



#include <iostream>

using namespace std;

unsigned int n=0;
unsigned int d=0;
unsigned int punkty=0;
unsigned int ile_razy=0;
unsigned int N=0;


void sortowanie_babelkowe(unsigned int *tab, unsigned int n) //dostaje oryginalna talice i ilosc liczb w tablicy czyli "n"
{
    for(int i=1; i<n; i++)
    {
        for(int j=n-1; j>=1; j--)
        {
            if(tab[j]>tab[j-1]) // sortuje roznaco, ale jak zmienimy na "<" to zacznie malejaco
            {
                int bufor;
                bufor=tab[j-1];
                tab[j-1]=tab[j];
                tab[j]=bufor;
            }

        }
    }
}

void sortowanie_babelkowe2(unsigned int *tab, unsigned int n) //dostaje oryginalna talice i ilosc liczb w tablicy czyli "n"
{
    for(int i=1; i<n; i++)
    {
        for(int j=n-1; j>=1; j--)
        {
            if(tab[j]<tab[j-1]) // sortuje roznaco, ale jak zmienimy na "<" to zacznie malejaco
            {
                int bufor;
                bufor=tab[j-1];
                tab[j-1]=tab[j];
                tab[j]=bufor;
            }

        }
    }
}



int main()
{
    cin>>d;

    if((1<=d) && (d<=500))
    {
        for(int u=0; u<d; u++)
        {
            //cout << "Podaj liczbe zawodnikow: " << endl;
            cin>>n;

            if((1<=n) && (n<=200))
            {
                unsigned int *tablica;
                tablica=new unsigned int[n];


                for(int y=0; y<n; y++)
                {
                    cin>>punkty;
                    if(punkty<=1000)
                    {
                        tablica[y]=punkty;
                        punkty=0;
                    }

                }


                sortowanie_babelkowe(tablica,n);


                //cout<<"Po 1 posortowaniu 1 tablicy: ";
                /*
                for(int i=0; i<n; i++)
                {
                    //cout<<tablica[i]<<" ";
                }
                */

                // patrzymy ile liczb jest takich samych punktowo

                for(int z=0; z<n; z++)
                {
                    if(tablica[0]==tablica[z])
                        ile_razy++;
                }

                //cout<<"Ile razy: "<<ile_razy<<endl;



                // SORTUJEMY JAK BY 2 CZESC TEJ TABLICY MALEJACO
                N=n-ile_razy;

                unsigned int *tablica2;
                tablica2=new unsigned int[N];

                for(int r=N; r>=0; r--)
                {

                    tablica2[r]=tablica[r+ile_razy];

                }
                /*
                                //cout<<"Wyglad 2 tablicy: ";
                                for(int i=0; i<N; i++)
                                {
                                    //cout<<tablica2[i]<<" ";
                                }
                */
                sortowanie_babelkowe2(tablica2,N);


                //cout<<endl;

                /*
                                //cout<<"Po 1 posortowaniu 2 tablicy: ";
                                for(int i=0; i<N; i++)
                                {
                                    //cout<<tablica2[i]<<" ";
                                }
                */
                // cout<<endl;

                unsigned int *tablica3;
                tablica3=new unsigned int[n];


                for(int i=0; i<n; i++)
                {
                    tablica3[i]=tablica[i];
                }


                for(int i=0; i<N; i++)
                {
                    tablica3[ile_razy+i]=tablica2[i];
                }



                //cout<<"Koniec zadania: ";
                for(int i=0; i<n; i++)
                {
                    cout<<tablica3[i]<<" ";
                }
                cout<<endl;


                punkty=0;
                ile_razy=0;

                delete[]tablica;
                delete[]tablica2;
                delete[]tablica3;
            }
        }




    }


    return 0;
}
  • created

    Apr '17
  • last reply

    Nov '20
  • 68

    replies

  • 4.0k

    views

  • 14

    users

  • 19

    likes

  • 21

    links

Frequent Posters

There are 68 replies with an estimated read time of 13 minutes.

Przez chwilę kusiło mnie by stwierdzić, że uznanie Twojego kodu za coś tragicznego brzmi trochę jak uznanie Hitlera za judeosceptyka, ale jednak nie jest tak źle :wink: Pytanie dlaczego w ogóle odniosłem wrażenie, że może być tak źle?

1) Przyzwyczajaj się do angielskich nazw zmiennych i ogólnie do inglisza. W programowaniu nie brakuje międzynarodowych grup pracujących nad jakimś kodem, a patriotyzm sprowadza się do tego, że program jest kojarzony z konkretnym krajem, jak Windows z USA :wink: Polskie nazwy zmiennych są przestarzałe i należy się ich absolutnie wystrzegać.
2) Sortowanie bąbelkowe jest beee. Może być na start, ale no... ja przy tym zadaniu zaklepałem chyba pierwszy i na pewno jeden z ostatnich razy w życiu quicksorta. Tobie również to zalecam.
3) Dwa sortowania babelkowe? Nie lepiej jedno sortowanie i zmienna bool określająca czy sortowanie ma być rosnące czy malejące? To dużo mniej kodu... i dużo lepszy nawyk na przyszłość. Metoda copy-paste oczywiście na SPOJu przejdzie, ale nie jestem pewien czy rozumiesz jak krytyczny błąd właśnie popełniłeś i dlaczego. W dużym uproszczeniu programowanie polega na pisaniu logicznych i zrozumiałych rzeczy, a wiele programów użytkowych to setki tysięcy linii kodu. Jeżeli będziesz miał tabelę zawierającą 20 kolumn to nie zrobisz przecież 20 funkcji odpowiedzialnych za jej sortowanie kolejno wg pierwszej drugiej, ..., dwudziestej kolumny. W takim przypadku wyślesz do funkcji odpowiedniego inta, który powie wg której kolumny należy wykonać sortowanie. Podobnie tutaj - zmienna bool powie czy posortować to malejąco czy rosnąco.
4) if((1<=d) && (d<=500)) - wywal to dziadostwo (inne tego rodzaju syfy ofc też). Na SPOJu wychodzisz z założenia, że autor przestrzega specyfikacji wejścia. Jeżeli autor tego nie robi to masz wszelkie podstawy by uznać że zadanie jest beee i nie warto tracić na nie czasu. Sam powiedz, skoro autor mówi, że liczby na wejściu będą np. mniejsze niż 100 a są większe niz 1000000 to czy warto wierzyć mu na słowo, że zadanie polega np. na ich posortowaniu w kolejności rosnącej? Jeżeli ktoś nie umie określić wejścia do programu to co dopiero opisać co ten program ma robić... szczęśliwie na SPOJu mało jest zepsutych zadań / nie ma zepsutych zadań więc po prostu ify tego rodzaju wyrzucasz i jest fajnie :wink:
5) Wywal też okomentowane fragmenty kodu. Rozumiem, że pomagały Ci one w analizie efektów Twojej pracy - ok. Ale mi i każdemu innemu utrudniają debugowanie programu. Komentarz ma być krótki, jak jest to w Twoich procedurach sortujących. Wszelkie cout << "Podaj liczbe zawodnikow: " << endl; przeszkadzają w odczytaniu Twoich intencji.
6) Jeżeli piszesz kod na zmiennych globalnych to ok. Oczywiście to tragedia i porządne kody raczej nie zawierają zmiennych globalnych, ale na SPOJu jest to jednak dopuszczalne jeżeli nie zalecane i trudno nazwać to uchybieniem. Jednak jeżeli już używasz zmiennych globalnych to używaj ich raz a porządnie, bo unsigned int *tablica w mainie utrudnia zrozumienie kodu i jest to proszenie się o błąd.
7) Skoro korzystasz ze zmiennych globalnych, np unsigned int n=0 to po co wysyłasz n do funkcji jako argument? To bez sensu...
8) tablica2[r] = tablica[r + ile_razy]; - prosisz się o guza. Valgrind szaleje więc wg mnie nawet udało Ci się go nabić :wink: Generalnie: r = N a tablica2 jest rozmiaru N. Jak wiesz, tablice numerowane są od zera. W związku z tym tablica tab[5] ma 5 elementów: 0, 1, 2, 3, 4. Ostatni element takiej tablicy to tab[4]. W ogólności, dla naturalnego n tab[n] ma n elementów, a ostatni element to tab[n-1]. Odwołując się do tablica2[r] już próbujesz wywalić pamięć, choć jeszcze jej nie wywalasz - wszak to tylko zadania łatwe. Jednocześnie ile_razy jest >= 0 więc już w ogóle bawisz się np mając tab[5] i pisząc w elemencie tab[5+3]... W sumie nie zdziwiłbym się gdyby analiza tego fragmentu kodu rozwiązała Twój problem. Jednak jest późno więc ja rezygnuję :wink:
9) Komentarze, o czym dowiesz się także tutaj https://google.github.io/styleguide/cppguide.html10 to nie jest byle co. Twój komentarz ma być cenną wskazówką. Dlaczego jeden komentarz piszesz wielkimi literami a inne małymi? Przez pewien czas sądziłem, że po prostu stworzyłeś coś tak dzikiego i genialnego że muszę przeczytać kod trzy razy nim to zrozumiem. Nie wiem co gorsze: to, że komentarz iż sortujesz coś malejąco dotyczy instrukcji N = n - ile_razy; czy to, że jest z wielkiej litery. Szczerze - nie mam pojęcia co i jakim cudem sortuje N = n - ile_razy, ale ostatecznie wychodzi na to że napisałeś komentarz który jedynie wprowadza w błąd bo żadnego sortowania nie ma. Do tego napisałeś to wielkimi literami przez co ktoś czyta komentarz zamiast kodu i zastanawia się co też autor miał na myśli...
10) Zeruj zmienne na początku a nie na końcu. Twoje podejście oczywiście też jest formalnie rzecz ujmując ok, ale lepiej czyta się kod widząc "o! Tu zeruję zmienną i dalej jej używam". Trochę mi zajęło zauważenie, że robisz to dopiero na końcu.
11) Jest późno więc powiem Ci jak szybko to naprawić by dostać AC: usuń wszystkie delete :wink: A na przyszłość wiesz już co poprawić.

PS
No właśnie, jest późno i po przeczytaniu tego co napisałem uważam, że nie jest to tak logiczne i słuszne jak mi się wydawało. Ściślej - to co napisałem nie oddaje moich myśli. Ale trudno - zadań na SPOJu nie brakuje więc sam się z czasem wszystkiego nauczysz. Jak czegoś nie rozumiesz w mojej wypowiedzi to uznaj że godzina 1:40 w nocy nie służy używaniu mózgu i pomiń to :wink:

Dziękuję Ci bardzo za wyczerpującą wypowiedz na temat mojego kodu :slight_smile:
Wiem, teraz gdy na to spojrzałem wygląda to tragicznie, jednak na swoje usprawiedliwienie ( wiem że marne :smiley: ) powiem, że ten kod to to co jako pierwsze wpadło mi do głowy z racji tego, że moje umiejętności nie są jeszcze tak rozwinięte by napisać coś lepszego.

W wolnej chwili postaram się poprawić ten kod, jeszcze raz dzięki :wink:

Nie nigdzie nie widziałem [nawet na SPOJ,u] takiego zalecenia:
"HALO, używaj zmiennych globalnych, bo są super!."
Wprost przeciwnie: http://discuss.spoj.com/t/dlaczego-zmienna-globalna-jest-fuj/21824

Jeżeli jednak twoim, czy twoim, priorytetem jest uzyskanie AC i tylko to, to w tym momencie zupełnie przestaje mieć znaczenie dobry styl programowania i staje się bez znaczenia czy używasz zmiennych globalnych, piszesz kod nie używając modułów, funkcji, klas, struktur, dobrych komentarzy i dobrych nazw zmiennych, używasz odstępów poziomych i pionowych itd.

ALE, ale, ale!! Spoj może służyć nie tylko do nauki algorytmów i pisania brzydkich kodów.
ALE, wtedy to już TY sam [czytelniku] musisz być swoim własnym sędzią lub prosić o ocenę swojego kodu i porady bardziej doświadczonego/ych kolegów.

PS
To, że u mnie [w code bloks, visual super duper 2019 itp] działa jest najstarszą wymówką programistów. To ma działać wszędzie indziej, a u Ciebie czy działa czy nie, jest w takim przypadku zupełnie bezznaczenia.

PS 2
To, że u Ciebie działa [w tym konkretnym przypadku], wynika z tego, że domyślnie w c/c++ nie są sprawdzane przekraczanie indeksów, czy inny dostęp do niezaalokowanej pamięci. Na SPOJ'u jest to sprawdzane w pierwszej kolejności i przy takiej próbie program jest od razu przerywany a nie dopiero gdy [może] spowoduje to problemy i "samodzielne" wysypanie się programu. Dlaczego u Ciebie nie wysypuje się? Problem polega na tym, że takie zachowanie nie zawsze kończy się katastrofową [małe słabe testy], ale..., ale, [:wink:] w sprzyjających okolicznościach tak - np odpowiednio duży test.

PS 3
Sorry, za braki lub nadmiar ',' w powyższym tekście :wink:

Masz rację, u mnie np kiedy dopiero się uczę programować priorytetem jest uzyskanie AC. Wiem jednak że prędzej czy później będę musiał się nauczyć jak pisać "ładny i funkcjonalny kod" :smiley: Na początku jest to trudne i dla tego jak wpada mi coś do głowy, to od razu sprawdzam czy jest to dobre rozwiązanie ( AC ). Często jednak nie wracam do starych kodów aby je poprawić, ale będę musiał to zrobić. :slight_smile:

Cześć!

Czy moglibyście mi podać testy dla którego mój program nie działa?
https://ideone.com/ceMArc23
Wydaje mi się że uwzględniłem w nim wszystko (włącznie ze spacjami na końcach tekstów). Mimo tego brak AC.

Pozdrawiam

Tyle, że to nie o te spacje chodziło i chodzi.
Te, które uwzględniłeś są bez znaczenia - ich istnienie jest całkowicie akceptowane przez sędziego, w przeciwieństwie do tych drugich [w stdin], których nie akceptuje twój program i po prostu, najnormalniej w świecie, wywala się: https://ideone.com/dg0Te334

Te, które uwzględniłeś są bez znaczenia - ich istnienie jest całkowicie akceptowane przez sędziego, w przeciwieństwie do tych drugich [w stdin], których nie akceptuje twój program i po prostu, najnormalniej w świecie, wywala się

Przecież te dane dla których się wywala są TAKIE SAME, naprawdę czegoś stąd nie rozumiem...

Pozornie tak, ale tych spacji, których Ty nie widzisz na końcu danych, twój program widzi je doskonale i nie toleruje - może poczytaj o tym więcej? :wink:

1 2 3 4 5 <--ty jest spacja

1 2 3 4 5<-- tu nie ma spacji

PS
Czy nadal uważasz, że to takie same dane, dla innych języków przeważnie tak, ale dla twojego języka programowania i dla takiej metody wczytywania juyż nie jest to to samo.

PS 2
Możesz sobie zaznaczyć te dane, myszą, i wtedy powinieneś dostrzec różnicę między moiimi i twoimi danymi [w stdin]

No dobra ale... po co na wejściu po liczbie podawać spacje? O tym nie ma nigdzie żadnych informacji, wpisuję ostatnią liczbę i eneter a nie spacja :expressionless:

Może poczytaj sobie. Także to co wcześniej napisałem?

PS
Twoje wyjście [stdout - to czy ty wypisujesz na końcu linii spacje _ enter, czy nie] jest tu zupełnie bez znaczenia.

PS 2
Czy tego też nie widzisz: https://ideone.com/dg0Te318 <-- że twój program się na takich danych sypie? Przecież na "oko" wejście jest identyczne?

Przeczytałem doskonale to co wcześniej napisałeś i nie rozumiem dlaczego po liczbie muszę podawać jeszcze spacje, to jest bezsensu, nie ma takich informacji w zadaniu.

PS: widzę doskonale te spacje, tylko nie rozumiem po co je tam umieszczać?

W końcu

To trochę pytanie filozoficzne, możesz spytać autora, chociaż gdybyś trochę pomyślał, może sam znalazłbyś odpowiedz?

mniej więcej jak wyżej, nie będę się kłócił, czy to jest z sensem czy bez, chociaż ja widzę sens.

że tak spytam, no i co z tego?

Więc ja się spytam, po co używasz takiego języka, zamiast c/c++, w którym nie miałbyś z tym takich problemów?
Czemu używasz takiej dziwnej metody wczytywania liczb w swoim języku - nie masz tam innych. Nie pytaj bo ja nie znam twojego języka [programowania].

Więc może przeczytaj dokłądniej, to co znalazłeś? :wink:

PS
Wiem, co piszę, bo czasami coś piszę :wink:

PS 2
dokładniej

A czemu nie? :wink:

Czemu nie ma sensu? Jak wspominałem, w innych językach to żaden problem i może:

to był jednak zły wybór?

Dlaczego zły wybór? Ja tam sobie chwalę