Strona główna » Algorytmy » Artykuły » Narysuj Ślad
 

Narysuj Ślad

Treść

Narysuj linie podążając za prostymi wskazówkami. Na wejściu otrzymujemy instrukcje rozdzielone znakiem spacji. Każda instrukcja składa się z litery (U, D, L lub R co oznacza kolejno w górę, w dół, w lewo, w prawo) oraz liczby.

Zadanie polega na narysowaniu linii podążając za wskazówkami. Rysowanie zaczyna się od lewego-górnego rogu. Nieodwiedzone pola należy przedstawić podkreślnikiem \'_\', a odwiedzone \'0\'. Pola mogą być odwiedzona dwukrotnie. Przykładowo dla:

  1. R9 D6 L9 U4 R7 D2 L5

wynikiem powinno być:

  1. 0000000000
  2. _________0
  3. 00000000_0
  4. 0______0_0
  5. 0_000000_0
  6. 0________0
  7. 0000000000

Implementacja

Spostrzeżenia

Tablica powinna być dynamiczna, aby uniknąć podwójnego przeglądania ciągu instrukcji. Potrzebujemy wyodrębnić instrukcje z pobranej wejściowej linijki tekstu, ponieważ nie mamy podane ile instrukcji łącznie będzie.

Rozwiązanie

W celu optymalizacji wykorzystania pamięci program będzie automatycznie poszerzał tablicę jeśli zaistnieje taka potrzeba. Do tego będzie służyć funkcja poszerz(), która podaną tablicę tab i pozycji (ax, ay) upewni się, że tablica nie jest za mała.

C++
C#
  1. static void poszerz(ref List<List<char>> tab, int ax, int ay) {
  2.   if (tab.Count <= ay)
  3.     for (int i = tab.Count; i <= ay; i++) {
  4.       tab.Add(new List<char>(0));
  5.       for (int j = 0; j < tab[0].Count; j++)
  6.         tab[i].Add('\0');
  7.     }
  8.   if (tab[0].Count <= ax)
  9.     for (int i = 0; i < tab.Count; i++)
  10.       for (int j = tab[i].Count; j <= ax; j++)
  11.         tab[i].Add('\0');
  12. }

Funkcja pomocnicza porownaj() będzie porównywać dwa znaki i zwracać 1 jeśli są identyczne i 0 jeśli nie. Będzie ona wykorzystywana do określania przesunięcia śladu.

C++
C#
  1. static int porownaj(char a, char b) {
  2.   return (a == b) ? 1 : 0;
  3. }

Funkcja Główna

W głównej funkcji następuje deklaracja zmiennych, których będziemy uzywać: tab - będzie przechowywać tablicę pól, które zostały (nie)odwiedzone, ax i ay - współrzędne aktualnego położenia rysowania, r - zmienna pomocnicza mówiąca ile pól należy przesunąć w daną stronę, f - zmienna przechowująca kierunek określony w instrukcji oraz lista, która przechowuje instrukcje zawarte w wprowadzonej linijce tekstu.

C++
C#
  1. static void Main(string[] args) {
  2.   List<List<char>> tab = new List<List<char>>();
  3.   int ax = 0, ay = 0, r;
  4.   char f;
  5.   string wyraz;

Druga część wczytuje dane i rozdziela tak, aby każda komenda była dostępna na liście jako oddzielny element.

C++
C#
  1.   Console.WriteLine("Podaj dane:");
  2.   wyraz = Console.ReadLine();
  3.   string[] lista = wyraz.Split(' ');

Część trzecia to pętla wywoływana dla każdego elementu z listy. Najpierw rozbija instrukcje na zmienne i zapisuje do f określony kierunek i do r ilość kroków. Następnie póki kroki się nie skończą zmieniane są wartości współrzędnych ax i ay. Przed przypisywaniem w danym polu wartości odwiedzenia wywołujemy funkcję rozszerz(), aby uniknąć problemów z wyjściem poza zakres tablicy.

C++
C#
  1.   for (int i = 0; i < lista.Length; i++) {
  2.     f = lista[i][0];
  3.     r = Convert.ToInt32(lista[i].Substring(1, lista[i].Length - 1));
  4.     while (r-- > 0) {
  5.       ax += porownaj(f, 'U') * -1 + porownaj(f, 'D');
  6.       ay += porownaj(f, 'L') * -1 + porownaj(f, 'R');
  7.       poszerz(ref tab, ay, ax);
  8.       tab[ax][ay] = '0';
  9.     }
  10.   }

Czwarta część jest to wypisywanie wyniku. To właśnie tu określamy jak dana wartość pola ma być interpretowana.

C++
C#
  1.   for (int y = 0; y < tab.Count; y++) {
  2.     for (int x = 0; x < tab[y].Count; x++)
  3.       Console.Write(((tab[y][x] == '\0') ? '_' : '0'));
  4.     Console.WriteLine();
  5.   }

Kończymy pracę programu wpierw zatrzymując wykonywanie programu, aby użytkownik mógł przeczytać wyjście, a po naciśnięciu dowolnego przycisku program jest zamykany.

C++
C#
  1.   Console.ReadKey();
  2. }