• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

[c#] Parkingowe zadanie - prośba o ocenę :)

Object Storage Arubacloud
+1 głos
389 wizyt
pytanie zadane 11 września 2017 w C# przez konrad9001 Początkujący (400 p.)
edycja 11 września 2017 przez konrad9001

Witam! Na początek chciałbym się przywitać z użytkownikami forum, ponieważ jest to mój pierwszy wpis. W programowaniu również jestem stosunkowo świeży, ale to nie czas na opowiadanie mało interesujących życiowych historii ;)

Jakiś czas temu trafiłem na portal codewars.com, na którym można w bardzo fajny sposób przetestować zdobytą wiedzę rozwiązując rozmaite zamieszczane tam problemy. I właśnie w tej sprawie chciałbym się do Was zwrócić. Bawię się tam już od jakiegoś czasu i kilka zadań udało mi się rozwiązać, jednak idąc za radą ludzi mądrzejszych ode mnie, którzy nie jednokrotnie powtarzali, aby wyjść ze swoim kodem do ludzi i poddać go pod krytykę, zdecydowałem, że nadszedł czas aby się zebrać i pokazać moje chaotyczne linijki :D

Zajmowałem się ostatnio poniższym zadaniem:
https://www.codewars.com/kata/591eab1d192fe0435e000014

Dokładna treść jest podana w powyższym linku, natomiast w skrócie chodzi o to, że jesteśmy, na jakimś piętrze parkingu(jest to określone) i musimy zwrócić najkrótszą drogę na zewnątrz(czyli na parter i do wyjścia). Nie będę tutaj za dużo pisał, ponieważ dokładnie opisano to w linku, który podałem, a ja nie chcę tego powielać.

Przechodząc do sedna, poniżej zamieszczam moje rozwiązanie tego zadania:

 

namespace CodeWars
{
    public class Kata
    {
        public string direction(int position, int exit)
       {
            if (position - exit == 0) return "";
            return (position-exit>0) ? "L" + (position-exit) + " " : "R" + System.Math.Abs(position - exit) + " ";
       }

        public int[] foundTwo(int[,] carpark)
        {
            for(int i=0;i<carpark.GetLength(0);++i)
            {
                for (int j = 0; j < carpark.GetLength(1); ++j)
                {
                    if (carpark[i, j] == 2) return new int[2] { i, j };
                }
            }
            return new int[0];
        }



        public string[] escape(int[,] carpark)
        {
            int[] foundPosition = foundTwo(carpark);
            int position = foundPosition[1];
            int exit = -1;
            string answer = "";
            string[] answer_;
            int counter = 1;
            bool firstIteration = true;
            for (int i = foundPosition[0]; i <carpark.GetLength(0); ++i)
            {
                if (!firstIteration)
                {
                    if (carpark[i, position] == 1)
                    {
                        counter++;
                        continue;
                    }
                    answer += "D" + counter + " ";
                    counter = 1;
                }
                firstIteration = false;
                for (int j = 0; j < carpark.GetLength(1); ++j)
                {
                   if (carpark[i, j] == 1)
                   {
                        exit = j;
                        break;
                   }
                      
                }
                if (exit == -1)
                    exit = carpark.GetLength(1) - 1;
                answer += this.direction(position, exit);

                position = exit;
                exit = -1;
            }
            if (answer.Length > 0) answer_ = answer.Trim().Split(' ');
            else answer_ = new string[0];
            
            return answer_;
        }
    }
}

Chciałbym, aby ktoś kto byłby na tyle miły i chciałby poświęcić trochę czasu ocenił to rozwiązanie. Dopiero zaczynam taką poważniejszą zabawę w C#, przez co każde moje rozwiązanie uważam za przesadnie złożone. Może to złudne wrażenie, a może wcale nie, właśnie tego chciałbym się dowiedzieć, tzn. jak zdaniem innych osób prezentuje się powyższy kod.

Zanim jednak oddam go w Wasze ręce jeszcze kilka słów wyjaśnienia mojego procesu myślowego podczas jego budowy. Najpierw sposób budowania tablicy, która powinna zostać zwrócona. Na samym początku nie znamy jej rozmiaru i wydaje mi się, że nie sposób go jednoznacznie wyznaczyć już na starcie. W tym miejscu miałem w zasadzie dwa pomysły jak sobie z tym poradzić, pierwszy to wykorzystać typy generyczne używając klasy ArrayList, jednak nie czuje się jeszcze w tym temacie zbyt swobodnie. Nie chciałem długo ślęczeć nad dokumentacją, czego wymagałby poprzedni pomysł, dlatego też wymyśliłem to inaczej, tzn. utworzyć odpowiedź jako ciąg znaków(czyli klasa String), gdzie każdy element tablicy jest rozdzielony spacją, a następnie pocięcie tego przy użyciu metody Split i zapakowanie do tablicy, którą trzeba zwrócić. Wydaje mi się, że sposób taki jest mało profesjonalny.

Co do samego zadania, najważniejsze funkcje postanowiłem wyciąć, z głównego kodu programu i spakować w formie metod(te na samej górze, myślę, że dzięki temu to wszystko jest czytelniejsze i bardziej przejrzyste). W początkowej fazie programowania wyszukiwanie liczby 2 wykonywało się za każdym obrotem pętli. Pętla sprawdzała każdą liczbę i przyrównywała ją do 2 oraz do 1 i odpowiednio zapisywała. Stwierdziłem jednak, że dwójka może wystąpić tylko raz dlatego taki sposób jest mało optymalny, bo program robi coś co jest bezużyteczne. Kod z metody direction nie wymagał natomiast wycięcia, ale również wydaje mi się, że poprawiło to czytelność.

Samo działanie kodu jest następujące:
1. Znajdujemy liczbę 2 oraz zapisujemy numer piętra i (indeks) pozycję tej liczby w tablicy
2. Pozycję przypisujemy zmiennej Position
3. Do zmiennej exit przypisujemy wartość -1(w tej zmiennej będzie przechowywany indeks miejsca, gdzie są schody)
4. Łańcuch answer będzie przechowywał odpowiedź przed pocięciem a tablica answer_ po pocięciu
5. Zmienna counter określa o ile pięter będziemy się opuszczać w dół, natomiast fistIteriaton określa, czy pętla dopiero się zaczyna czy też nie.
6. Wskakujemy w pętlę, iteracji ma być tyle ile pięter mamy do sprawdzenia(to na którym stoimy, oraz wszystkie pod nami)

Szukałem sposobu na rozwiązanie tego bez tej zmiennej(bool), jednak nie potrafię znaleźć metody. Chodzi głównie o to, że nie zawsze będziemy zaczynać od najwyższego piętra(więc np. warunek i>0 odpada) a na samym początku pętli znajduje się kod odpowiedzialny za zejście piętro niżej, dlatego przy pierwszym obrocie chcemy go ominąć.

7. Po przeskoczeniu kodu opuszczania piętra, w każdym kolejnym obrocie już chcemy go uwzględniać, dlatego zmienna bool jest odwracana.
8. Następna pętla szuka miejsca, gdzie są schody(czyli liczby 1), gdy to zrobi natychmiast przerywa pętlę. Jedynka jest tylko jedna, zatem nie ma potrzeby dalszego działania.
9.Jeśli liczba 1 nie została odnaleziona to zmienna exit ma wartość początkową a to oznacza, że na piętrze są same 0(czyli jesteśmy na parterze).
10.Jeśli jesteśmy na parterze to schody są najbardziej po prawo
11. Metodą direction z uzyskanymi danymi wyznaczam odpowiedni symbol, opisany w poleceniu(odejmuje miejsce, gdzie zacząłem od schodów i na tej podstawie ustalam w którą stronę i o ile się poruszam. Jeśli wynik jest równy 0 oznacza to, że nie ruszyłem się)
12. W tym momencie stoję tam, gdzie schody, więc position=exit natomiast exit wraca do wartości domyślnej
13. Wracamy na górę pętli i tym razem schodzę o piętro niżej, jeśli w miejscu, gdzie właśnie zeskoczyłem jest 1 to zwiększam liczbę pięter, które przeskakuję o 1 oraz pomijam iterację pętli(ponieważ nie muszę szukać schodów). Jeśli nie stoję na 1, to wyznaczam symbol i resetuje licznik.

I w taki sposób się to kręci, aż sprawdzę wszystkie piętra i potnę wynik. Ostatni if sprawdza, czy łańcuch jest dłuższy niż 0, w poleceniu powiedziano, że nie zacznę na schodach ale mogę zacząć na parterze, w miejscu, gdzie jest wyjście. Wtedy tablica będzie pusta, bo nie wyznaczę żadnego symbolu. Ostatecznie zwracam tablicę z odpowiedziami.

Wybaczcie, że nieco się rozpisałem, ale chciałem mniej więcej dobrze opisać co i jaką funkcję miało spełniać w rozwiązaniu. Jeśli ktoś byłby na tyle miły aby przez to przebrnąć i ocenić sposób rozwiązania tego zadania(a przede wszystkim sam kod) to byłbym wdzięczny, wszelkie wskazówki będą dla mnie bardzo cenne ponieważ bardzo zależy mi na jak najrzetelniejszej nauce programowania.

Z góry dziękuję za odpowiedzi i wytrwałość :)

 

1 odpowiedź

0 głosów
odpowiedź 12 września 2017 przez pulson666 Stary wyjadacz (12,560 p.)
wybrane 13 września 2017 przez konrad9001
 
Najlepsza

Na samym początku nie znamy jej rozmiaru

Co do samej tablic w tym kodzie - kiepsko, C# ma coś pięknego czego nie ma c++ czyli Listy, użyj Listy zamiast tablicy, będziesz miał większą pewność, że się nic nie wysypie, oraz wiele dodatkowych funkcji. 

Z Listą również wiąże się pętla foreach ( poczytaj bo jest najczęściej używana) 

Kolejna sugestia raczej. Piszesz "if(true) return coś" I jest to jak najbardziej poprawne, lecz każda szkoła mówi inaczej. Po pierwsze według zasad SOLID powinieneś wszystko pisać tak samo czyli  użyć klamry "if(true) { return coś } " lecz tutaj inni mówią że to jest wyjątek :p. Po drugie gdy ktoś usunie przypadkiem to return to wywoła się kod następny przez co nagle się wszystko posypie.

P.S. Ja pisze tak samo jak Ty :p lecz chciałem Ci to powiedzieć byś miał świadomość taką na rozmowach kwalifikacyjnych  ;)

Zapewne znasz różnice pomiędzy ++i a i++ , pytam tylko czy jesteś świadomy ;)

 

kod wygląda ogólnie ok jak i użyta logika. Nie wiem czy na wszystko odpowiedziałem tak jak chciałeś bo dość bardzo się rozpisałeś :p

 

komentarz 12 września 2017 przez QizmoPL Stary wyjadacz (11,440 p.)
c++  ma listy
komentarz 12 września 2017 przez pulson666 Stary wyjadacz (12,560 p.)
Masz na myśli vector? Szczerze nie wiem jak w cpp to teraz wygląda. Skoro są to szkoda, że ba studiach ich mi nie pokazali xd
komentarz 12 września 2017 przez QizmoPL Stary wyjadacz (11,440 p.)
komentarz 13 września 2017 przez konrad9001 Początkujący (400 p.)

Głównie chodziło mi o to, żeby ktoś inny(niż ja) zerknął na kod i powiedział co nieco o strukturze, więc Twoja odpowiedź jest dla mnie satysfakcjonująca smiley

Co do List to od początku wiedziałem, że pomijając je tu robię głupotę, bo metoda którą zastosowałem jest raczej mocno amatorska(takie miałem wrażenie pisząc ten kod). Idąc za Twoją radą wezmę się mocniej za listy i postaram się to przepisać używając ich.

Co do ifów to może racja, że nie jest to najlepsza praktyka ale jakoś tak zawsze pisałem i już mi tak zostało ale dzięki za zwrócenie uwagi. A co do ++i i i++ różnica jak najbardziej oczywista laugh

Dziękuję za odpowiedź ;)

komentarz 13 września 2017 przez QizmoPL Stary wyjadacz (11,440 p.)
tak na przyszlosc, nie rozpisuj sie az tak
komentarz 15 września 2017 przez pulson666 Stary wyjadacz (12,560 p.)
Jak na początkującego to bardzo ładny kod ;)

Podobne pytania

0 głosów
0 odpowiedzi 180 wizyt
pytanie zadane 28 sierpnia 2019 w C# przez pewien_programista Obywatel (1,070 p.)
0 głosów
0 odpowiedzi 118 wizyt
pytanie zadane 20 grudnia 2019 w C# przez Windows Nowicjusz (150 p.)
0 głosów
1 odpowiedź 1,035 wizyt
pytanie zadane 31 lipca 2018 w JavaScript przez ogórek Nowicjusz (150 p.)

92,543 zapytań

141,385 odpowiedzi

319,491 komentarzy

61,929 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...