Zadania

Pliki

Kolonizacja marsa (RBS)

18 października 2016 20:00

CyberJaś jest głównym oficerem łączności w trakcie misji kolonizacyjnej Marsa. Obszar planety podzielony został na dystrykty wraz z lokalnym centrum dowodzenia, które znajduje się pośrodku każdego z nich. W trakcie konfigurowania łączności między dystryktami Jasiu natrafił na problem… niektóre z sąsiadujących ze sobą baz zagłuszały się wzajemnie. Okazało się że nadają na zbyt zbliżonych częstotliwościach. Jasiu ma do dyspozycji ograniczoną ilość częstotliwości. Pomóż mu rozdzielić częstotliwości tak, aby zapewnić dystryktom stałą, niezakłóconą łączność z Ziemią.

 

Ze względu na zmienne warunki parametry mapy częstotliwości mogą się zmieniać. Tak samo rozmiar mapy, gdyż z czasem obszar pokryty zasięgiem będzie rósł. Zasady nadal są proste:

 

  • Dystrykty są kwadratami. Każdy sąsiaduje z maksymalnie ośmioma innymi. 
  • Zbadano, że częstotliwości w sąsiadujących dystryktach zagłuszają się jeśli różnica jest mniejsza niż minDiff (wartość zależy od warunków atmosferycznych i jest podawana jako argument przy rozmieszczaniu częstotliwości). 
  • Mapa ma zmienny rozmiar A obszarów (kolumn) na B obszarów (wierszy). Także podawane jako argumenty. 
  • Dostępne częstotliwości są przydzielane przez Ministerstwo Telekomunikacji i też są zmienne (ich ilość jak i wartości). Są podawane jako argument (jako lista nieposortowana). 

 

Mapa wyliczona przez Jasia powinna mieć postać listy o rozmiarze A*B gdzie kolejne wartości reprezentują kolejne wiersze.

 

Poniżej znajduje się przykład poprawnej mapy gdzie A = 7, B = 5, minDiff = 3, częstotliwości to: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16. Małe indeksy w rogu obszarów reprezentują kolejne indeksy w zwróconej liście.

 

 

Natomiast tak wygląda niepoprawnie stworzona mapa (z błędami zaznaczonymi na czerwono):

 

 

Możliwe jest, że nie da się rozmieścić częstotliwości na mapie tak, aby się nie zagłuszały. Wtedy należy zwrócić pustą listę. 

Nie jest wymagane, żeby wykorzystać wszystkie dostępne częstotliwości. 

 

Rozwiązanie powinno implementować interfejs IFrequencyDistributor. Wysyłamy jeden plik kodu źródłowego zawierający tylko i wyłącznie klasę implementującą interfejs. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Parser

17 października 2016 20:00

Agent jednostki specjalnej, pseudonim CyberJaś, znów stanął przed nie lada wyzwaniem. Tym razem misja dotyczyła przechwycenia i rozszyfrowania danych agentów, przesyłanych między dwoma wrogimi mocarstwami. Misja zakończyła się sukcesem. CyberJasiowi udało się przechwycić dane, jednak  po ich rozszyfrowaniu okazało się, że dane są przekazywane w formacie zbliżonym do vCarda. Pomóż Jasiowi napisać parser, który umożliwi zapisanie danych o agentach w strukturach, które są łatwiejsze w późniejszej analizie. 

 

Parser (IParser::parse()) jako parametr przyjmuje dane w konkretnym formacie (pseudo vCard, elektroniczna wizytówka). Dane mogą być przekazywane do parsera w paczkach o różnych długościach. W paczce może się znaleźć kilka wizytówek, jak również jedynie część wizytówki, w takim przypadku reszta będzie dostarczona w następnej paczce (przy kolejnym wywołaniu metody IParser::parse()). Parser przez wywołanie odpowiedniego callbacka (IParserListener::newVCard()) zwraca obiekt (typu vCardStruct) zawierający otrzymane i przetworzone dane. Powinien on być zwrócony w chwili kiedy wszystkie dane dotyczące danego obiektu (wizytówki) zostały otrzymane.

Metoda IParser::parse() może zwrócić status:

  • PARSE_STATUS_OK – wszystkie wizytówki z paczki zostały przeparsowane, paczka nie zawierała niepełnej wizytówki
  • PARSE_STATUS_MORE_DATA – wszystkie całkowite wizytówki z paczki zostały przeparsowane, do przeparsowania ostatniej, niepełnej wizytówki potrzebna jest kolejna paczka danych
  • PARSE_STATUS_ERROR – oznacza błąd podczas parsowania (przyjmujemy jednak, że dane testowe są poprawne)

IParserListener jest jedynie interfejsem, tak więc do celów testowych w czasie implementowania rozwiązania, uczestnik sam powinien zadbać o jego implementację.

 

Opis formatu (uproszczony vCard): 

VCard jest to format pliku zawierającego dane osobowe (elektroniczna wizytówka). Dane jednej wizytówki zawierają się między znacznikami początku vCarda BEGIN:VCARD oraz końca END:VCARD

Dane osobowe są reprezentowane poprzez znaczniki i ich wartości, np. N:Jan Kowalski. W tym przypadku N jest znacznikiem, a Jan Kowalski wartością. Znacznik i jego wartość zawsze są rozdzielone dwukropkiem i kończą się dwuznakiem końca linii <CRLF> (ASCII 13 i ASCII 10). Znacznik początku vCarda również jest zakończony <CRLF>, natomiast znacznik końca może, ale nie musi. 

Poprawne znaczniki to: 

  • N – Name, oznacza nazwę lub imię i nazwisko 
  • ADR – Address, oznacza adres 
  • TEL – Telephone, oznacza numer telefonu 
  • EMAIL – Electronic mail, oznacza adres e-mail 
  • PHOTO – Photograph, oznacza zdjęcie zapisane binarnie za pomocą ograniczonego zbioru znaków: A-Z, a-z, 0-9. Dodatkowo ciąg danych jest podzielony na linie, każda linia zawiera maksymalnie 78 znaków i jest zakończona dwuznakiem nowej linii <CRLF> niewliczającym się do wspomnianych 78 znaków.

 

Przykładowa wizytówka: 

BEGIN:VCARD<CRLF> 

N:Jan Kowalski<CRLF> 

PHOTO:oijasdcokmasodijcocmoijasdcokmasodIjcocmoijasdcokmasodijcocmoijasdcokmasodijco<CRLF> 

asodijcocmoijasdcokmasodijcocmoijasdcokmasOdijcocmoijasdcokmasodijcocmoijasdco<CRLF> 

asodijcocmoijasdcokYYJrr<CRLF> 

<CRLF> 

TEL:696 969 696<CRLF> 

ADR:ul. Dowborczykow 25, 90-993 Lodz<CRLF> 

EMAIL:jan.kowalski@cybercom.com<CRLF> 

END:VCARD   

 

Rozwiązanie powinno implementować interfejs IParser. Wysyłamy jeden plik kodu źródłowego C#, C++ lub Java. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Uwaga dla C++: Każda paczka danych (wektor) przekazywana jako parametr metody IParser::parse() jest zakończona znakiem ‘\0’, który należy zignorować.

Wieża Hanoi

14 października 2016 20:00

Według legendy pod kopułą indyjskiej świątyni znajduje się tablica z brązu, na której umieszczone są cztery diamentowe słupki. Na pierwszym z tych słupków znajdują się krążki z czystego złota o różnej średnicy ułożone od największego (na dole) do najmniejszego (na górze). Dniem i nocą mnisi z pobliskiego klasztoru przekładają krążki z jednego diamentowego słupka na drugi zgodnie z wyznaczonymi regułami. Mówią one, że krążki można przekładać pojedynczo i tylko na większy krążek (lub pusty palik).

Pomóż mnichom przenieść krążki mając do dyspozycji cztery paliki i maksymalnie szesnaście krążków, które są ponumerowane. Celem jest przełożenie krążków na dwa paliki, tak aby na trzecim znajdowały się numery parzyste, a na czwartym nieparzyste.

Rozwiązanie powinno implementować interfejs IHanoiSolver/HanoiSolver. Do rozwiązania problemu jest dostępne API (IHanoi/Hanoi) pozwalające na pobranie liczby krążków (która może być zerem), przenoszenie krążków oraz sprawdzanie jaki krążek jest na szczycie danego palika, w przypadku pustego palika zwracane jest -1. Zarówno paliki jak i dyski numerowanie są od zera. Jest to jedynie interfejs, tak więc do celów testowych w czasie implementowania rozwiązania, uczestnik sam powinien zadbać o jego implementację.

Wysyłamy jeden plik kodu źródłowego C#, C++ lub Java. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Przyjęcie

13 października 2016 20:00

Jesteś liderem w branży organizacji imprez dlatego nic dziwnego, że to właśnie do Ciebie zwrócił się rząd o zorganizowanie Światowego Kongresu Gospodarczego. Na 3 dni przed imprezą otrzymałeś długą listę gości zawierającą G pozycji oraz dokładne wytyczne, co do ich rozsadzenia. Wiesz, że masz do dyspozycji S stołów, a przy każdym z nich mieści się po M osób oraz, że: 

  • różnica wieku między najstarszą a najmłodszą osobą przy stoliku nie może wynosić więcej niż R
  • nikt nie może siedzieć sam przy stoliku – przy jednym stoliku muszą być przynajmniej 2 osoby
  • stoliki nie muszą być w pełni zapełnione, a niektóre mogą pozostać puste.

Hm… chyba za późno na główkowanie. Łatwiej będzie napisać algorytm, który zrobi to za Ciebie. 

 

Jako dane wejściowe otrzymasz wartości argumentów G, M, R, S oraz ciąg liczb całkowitych, które reprezentują wiek każdego z gości. 

Zakres danych: 0 < G,M,S <= 100, 0 <= R <= 100

Każde zadanie ma gwarantowane przynajmniej jedno poprawne rozwiązanie.

Rozwiązaniem zadania jest ciąg liczb całkowitych, który reprezentuje wiek usadzonych gości, tak, że pierwsze M liczb mówi o gościach przy pierwszym stole, następne M liczb mówi o gościach przy drugim stole itd. Jeśli miejsce przy stoiku jest puste, należy zamiast wieku podać cyfrę 0. 

 

Przykładowe dane: 

Tablica gości: [22, 31, 25, 24, 30] 

Liczba gości = 5 

Liczba stolików = 3  

Max. liczba gości przy stoliku = 4

Max. różnica wieku przy jednym stoliku = 8

 

Przykładowy poprawny wynik: 

[22, 30, 0, 24, 31, 0, 0, 25, 0, 0, 0, 0]

 

Wysyłamy jeden plik kodu źródłowego C#, C++ lub Java. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Udaremnij atak terrorystyczny (odwracanie funkcji)

12 października 2016 20:00

Rządowe Centrum Bezpieczeństwa zaczęło przechwytywać zaszyfrowane wiadomości, które mogą zawierać informacje dotyczące planowanego ataku terrorystycznego. Nad rozszyfrowaniem wiadomości pracował cały sztab specjalistów, niestety bez rezultatu. W końcu z udziałem tajnego agenta uzyskano metodę szyfrowania wiadomości. Ale nadal nikt nie dał rady odkodować treści. 

To już pewne - bezpieczeństwo narodowe jest zagrożone, a czasu pozostało niewiele. Jedyna nadzieja w CyberJasiu, który jak tylko poznał powagę sytuacji od razu przystąpił do pracy. 

Tajny agent twierdzi, że wiadomości są szyfrowane przez funkcję: 

C++:

unsigned long long code(std::string &what, std::string &alphabet) 

{     

    unsigned long long value = 3;

    for (unsigned int i = 0; i < what.size(); i++)

    {         

         value = value * 29 + alphabet.find(what.at(i));    

    }    

    return value; 

Java:

public static long code(String what, String alphabet) {

    long value = 3;

    for (int i = 0; i < what.length(); i++) {

        value = value * 29 + alphabet.indexOf(what.charAt(i));

    }

    return value;

}

C#:

public static long code(string what, string alphabet)

{

    long value = 3;

    for (int i = 0; i < what.Count(); i++)

    {

        value = value * 29 + alphabet.IndexOf(what[i]);

    }

    return value;

}

Oraz, że treść wiadomości nie zawiera jednorazowo więcej niż 12 znaków. Zapewnia także, że do każdego szyfru może dostarczyć odpowiedni alfabet użyty do szyfrowania. Alfabety mogą być różnej długości, ale zawsze mniejszej niż 29 znaków i zawsze składają się z niepowtarzalnych znaków.  

 

Rządowe Centrum Bezpieczeństwa oczekuje następującej funkcji odszyfrowującej:  

Result decode(unsigned long long value, std::string &alphabet) 

Funkcja ma zwrócić strukturę/klasę Result składającą się z informacji czy odszyfrowywanie się powiodło (w postaci ResultCode który może mieć wartość SUCCESS dla sukcesu oraz FAILURE przy porażce) oraz w razie sukcesu, ciągu znaków stworzonego przy pomocy podanego alfabetu, który odpowiada danemu szyfrowi. 

 

PRZYKŁAD:

code("aabc", "abcde") zwróci 2121874 

code("ddaaab", "gfedcab") zwróci 1848251554 

 

Oraz 

decode(2121874, "abcde") zwróci {SUCCESS, "aabc"} 

decode(20, "abcde") zwróci {FAILURE, ""} 

 

W wybranym języku należy zaimplementować odpowiednią klasę abstrakcyjną używając dostarczonych z nim struktur (Result i ResultCode): 

C++ – IDecoder 

Java – Decoder 

C# – IDecoder

Wysyłamy jeden plik kodu źródłowego zawierający tylko i wyłącznie klasę implementującą klasę abstrakcyjną. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Kupno i Sprzedaż Akcji

11 października 2016 20:00

Jako makler giełdowy dostałeś do analizy roczny kurs akcji pewnej spółki. Trzeba ustalić ile maksymalnie można było na niej zarobić pieniędzy w tym okresie, aby stwierdzić czy warto w tę spółkę inwestować w kolejnych latach. Przyjęto założenie, że można kupić tylko jedną akcję tylko jeden raz w dowolnym momencie, a następnie sprzedać ją w późniejszym terminie. Chodzi o to, aby akcję kupić po możliwie najniższej cenie, a sprzedać możliwie po najwyższej aby zmaksymalizować swój zysk. Odpowiedź powinna zawierać wartość maksymalnego zysku jak również momenty kupna i sprzedaży akcji (będą to wartości indeksów tablicy). Przyjmujemy, że dane wejściowe zawierają przynajmniej jeden zysk. Jeśli istnieją dwa (lub więcej) zyski o tej samej wartości, którykolwiek z nich jest uznawany jako poprawny. Tablica wejściowa posiada zmienny rozmiar z zakresu od 2 do 1000000 elementów i jest indeksowana od 0.

 

Na przykład dla tablicy wejściowej:

5, 10, 2, 1, 3, 4, 9, 9, 8, 8

Maksymalny zysk to 8, a indeksy: 3 i 6.

 

Rozwiązanie powinno implementować abstrakcyjną klasę IStockExchangeProfit. Wysyłamy jeden plik kodu źródłowego zawierający tylko i wyłącznie klasę konkretną implementującą klasę abstrakcyjną. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Jako makler giełdowy dostałeś do analizy roczny kurs akcji pewnej spółki. Trzeba ustalić ile maksymalnie można było na niej zarobić pieniędzy w tym okresie, aby stwierdzić czy warto w tę spółkę inwestować w kolejnych latach. Przyjęto założenie, że można kupić tylko jedną akcję tylko jeden raz w dowolnym momencie, a następnie sprzedać ją w późniejszym terminie. Chodzi o to, aby akcję kupić po możliwie najniższej cenie, a sprzedać możliwie po najwyższej aby zmaksymalizować swój zysk. Odpowiedź powinna zawierać wartość maksymalnego zysku jak również momenty kupna i sprzedaży akcji (będą to wartości indeksów tablicy). Przyjmujemy, że dane wejściowe zawierają przynajmniej jeden zysk. Jeśli istnieją dwa (lub więcej) zyski o tej samej wartości, którykolwiek z nich jest uznawany jako poprawny. Tablica wejściowa posiada zmienny rozmiar z zakresu od 2 do 1000000 elementów i jest indeksowana od 0.

 

Na przykład dla tablicy wejściowej:

5, 10, 2, 1, 3, 4, 9, 9, 8, 8

Maksymalny zysk to 8, a indeksy: 3 i 6.

 

Rozwiązanie powinno implementować abstrakcyjną klasę IStockExchangeProfit. Wysyłamy jeden plik kodu źródłowego zawierający tylko i wyłącznie klasę konkretną implementującą klasę abstrakcyjną. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Silnia - ile zer na końcu

10 października 2016 20:00

Tegoroczny egzamin do Najwyższej Szkoły Programowania przebiegał dla Jasia pomyślnie. Leciał zadanie za zadaniem, równanie za równaniem, kod za kodem, aż nagle… oniemiał. Ostatnie polecenie przeszło jego najśmielsze oczekiwania. Jednak z uwagi na to, że Jaś należy do osób lubiących wyzwania, pomyślał sobie „Kto jak nie ja?”. Czym prędzej zakasał rękawy i zabrał się do poszukiwania metody, która pozwoli mu na rozwiązanie ostatniego zadania. 

 

Zadaniem tym jest zaimplementowanie metody o parametrach (N,B), która policzy i zwróci liczbę zer na końcu zapisu silni podanej liczby N. Liczba N jest zapisana w systemie dziesiętnym, natomiast jej silnia ma być zapisana w systemie liczbowym o podanej podstawie B.  N może być dowolną liczbą całkowitą z zakresu 0 ≤ N < 2^31,  a B – dowolną liczbą całkowitą z zakresu 2 ≤ B ≤ 16. 

 

Na przykład, dla parametrów wejściowych: 

1) N = 11, B = 3

poprawną wartością zwracaną przez metodę jest 4, bo 11! = 2210002222120000 (3)

2) N = 13, B = 7

poprawną wartością zwracaną przez metodę jest 1, bo 13! = 310211542410 (7)

3) N = 15, B = 10 

poprawną wartością zwracaną przez metodę jest 3, bo 15! = 1307674368000 

4)  N = 30, B = 16 

poprawną wartością zwracaną  przez metodę jest 6, bo 30! = D13F6370F96865DF5DD54000000 (16)

 

 

Rozwiązanie powinno implementować abstrakcyjną klasę (I)FactorialTrailingZeros. Wysyłamy jeden plik kodu źródłowego zawierający tylko i wyłącznie klasę konkretną implementującą klasę abstrakcyjną. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Tajemnicze sygnały

7 października 2016 20:00

Pewnego wiosennego wieczoru CyberJaś oglądał telewizję. Nagle jego uwagę przykuły wiadomości i doniesienia nt. ciekawego zjawiska. W stanie Missouri w USA naukowcy zaobserwowali sygnały, które za pomocą tablicy 78 x 78 żarówek najprawdopodobniej były nadawane z kosmosu, jednak nikt nie jest w stanie ich rozszyfrować. NASA poprosiło wszystkich obywateli Świata o pomoc. Jaś obserwując nagranie dopatrzył się pewnej zależności, zakładając, że każda żarówka znajduje się w dwóch stanach: zgaszona (false) lub zapalona (true). CyberJaś stwierdził, że stan każdej żarówki zależy od swojego poprzedniego stanu oraz poprzedniego stanu wszystkich sąsiednich żarówek. Przez sąsiednie żarówki rozumiemy wszystkie stykające się – w pionie, poziomie oraz na rogach (8 lub mniej w przypadku żarówek na granicy tablicy):

  • żarówka zapalona pozostaje zapalona, jeżeli dokładnie 2 lub 3 sąsiednie żarówki są zapalone. W innym przypadku gaśnie.
  • żarówka zgaszona zapala się, jeżeli dokładnie 3 sąsiednie żarówki są zapalone. W innym przypadku pozostaje zgaszona. 
  • wszystkie żarówki mogą zmieniać swój stan tylko jednocześnie w tych samych odstępach czasu (np. 1 sekunda).
  • żarówki na rogach tablicy się wypaliły, zatem już nigdy nie będą mogły być zapalone

Eureka! Jaś mając podaną początkową konfigurację tablicy żarówek już wie ile żarówek będzie zapalonych po K kroków! A ty?

 

Opis danych wejściowych:

Na wejściu dostajemy ilość kroków K (0 < K <= 1000) oraz tablicę żarówek w ich początkowym stanie (krok 0).

Tablica jest tablicą wartości logicznych (bool) o rozmiarze 78x78.

 

Wyjście:

Na wyjściu oczekujemy pojedynczej liczby n oznaczającej ilość zapalonych żarówek po K krokach.

 

PRZYKŁAD:

Dla lepszego zobrazowania tablica ma rozmiar 6x6 oraz wartość ’true’ oznaczamy znakiem ‘#’ a wartość ‘false’ znakiem ‘.’ (kropka).

K (ilość kroków) = 4

Stan początkowy:

.#.#..

...##.

#..#.#

..##..

#.#..#

.###..

 

Stan po 1 kroku:

..###.

...#..

......

..##..

....#.

.###..

 

Stan po 2 krokach:

..###.

..###.

..##..

...#..

.#..#.

..##..

 

Stan po 3 krokach:

..#.#.

.#....

......

...##.

....#.

..##..

 

Stan po 4 krokach:

......

......

......

...##.

..#.#.

...#..

 

Po 4 krokach 5 żarówek pozostaje zapalonych. (Rozwiązaniem jest liczba 5)

Rozwiązanie powinno implementować klasę abstrakcyjną ILightBulbs/LightBulbs. Wysyłamy jeden plik kodu źródłowego zawierający tylko i wyłącznie klasę implementującą interfejs. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Dostarczenie paliwa na stację kosmiczną

6 października 2016 20:00

NASA szykuje kolejną ekspedycję kosmiczną. Tym razem celem jest dotarcie na księżyc i pozostawianie tam łazika, który będzie badał obieg ciał niebieskich. Wiąże się to z dostarczeniem dodatkowych X litrów paliwa do stacji kosmicznej, odpowiedzialnej za pozytywny przebieg misji. Paliwo ze względów bezpieczeństwa może być transportowane w ściśle określonych kontenerach i muszą być one wypełnione do pełna. Jaka jest najmniejsza liczba kontenerów, które należy załadować na statek aby zmieścić dokładnie X litrów paliwa, wiedząc, że do dyspozycji mamy N kontenerów o następujących pojemnościach: k1, k2, …, kN? 

Dodatkowe informacje:

  • W przypadku gdy żadna kombinacja kontenerów nie daje wymaganej ilości paliwa, funkcja powinna zwrócić 0.

 

PRZYKŁAD 1:

Dostępne są kontenery o pojemnościach: 20, 15, 10, 10, 8 i 5 litrów.  (UWAGA: interpretować to nalezy nastepująco: mamy jeden kontener o pojemności dwudziestu litrów, jeden piętnastolitrowy, dwa dziesięciolitrowe, jeden ośmiolitrowy i jeden pięciolitrowy)

X = 40 litrów 

Poprawna odpowiedź: 3 (20, 15 i 5 albo 20, 10 i 10).

PRZYKŁAD 2:

Dostępne są kontenery o pojemnościach: 42, 41, 4, 3, 1 i 1 litrów.

X = 44 litrów

Poprawna odpowiedź: 2 (41 i 3).

PRZYKŁAD 3:

Dostępne są kontenery o pojemnościach: 7 i 4 litrów.

X = 10 litrów 

Poprawna odpowiedź: 0 (nie ma mozliwości przewiezienia całego paliwa).

 

Rozwiązanie powinno implementować interfejs IContainers/Containers. Wysyłamy jeden plik kodu źródłowego zawierający tylko i wyłącznie klasę implementującą interfejs. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).

Konwerter

5 października 2016 20:00

Międzynarodowe Targi w Japonii dotyczące najnowszych rozwiązań technologicznych właśnie dobiegły końca. Podczas targów Jasiu był w swoim żywiole. Rozwiązania jakich do tej pory nie widział ukazywały się jego oczom i wprawiały go w coraz większe zdumienie. Jego kalendarz był pełen spotkań, biegał od stoiska do stoiska zafascynowany tym co widział, przy okazji zdobywając nowe kontakty biznesowe. Jaś zebrał całą masę elektronicznych wizytówek, które zapisane są w formacie CSV. Jednak jak nad tym wszystkim zapanować? Pomóż Jasiowi uporządkować dane dodając je do jego bazy kontaktów.  

 

OPIS: 

Zadanie polega na zaimplementowaniu konwertera danych, który po otrzymaniu danych na wejściu, w określonym formacie (bufor z danymi, z pliku *csv), wygeneruje skrypt SQL-owy. Skrypt musi zawierać poprawną składnię SQL oraz być we wskazanym formacie, który umożliwi wstawienie danych do wskazanej tabeli (SQL INSERT). Na wejściu użytkownik otrzyma: 

  • nazwę tabeli, dla której wygeneruje skrypt
  • typy danych (buffor  załadowany z pliku *csv, separatorem będzie średnik ';')
  • nazwy kolumn (buffor  załadowany z pliksu *csv, separatorem będzie średnik - ';')
  • dane (buffor  załadowany z pliksu *csv, separatorem będzie średnik - ';').

 

Wynikiem uruchomienia programu ma być lista zawierająca SQL-owy INSERT, składający się z listy elemetów tego zapytania, bez białych znaków. 

  

PRZYKŁAD: 

Użytkownik otrzyma bufor danych załadowany z pliku *.csv. Jeden bufor *.csv będzie zawierał typy danych dla kolejnych kolumn z tabeli, np: 

"STRING;STRING;INT;INT;INT;DATE\r\n" 

Drugi bufor *.csv będzie zawierał nazwy pól z tabeli, np: 

"Pesel;FirstName;LastName;City;Street;StreetNo;Email;Login\r\n" 

Natomiast kolejny będzie zawierał dane (uwaga, nie wszystkie dane muszą się pojawić!), np: 

"0000000000000;Ala;Kowalska;Lodz;Pilsudskiego;121;Ala1@wp.pl;Ala666\r\n 

 0000000000001;Adam;Kowalskai;Lodz;;;mojemial1@wp.pl;adam1\r\n 

 …" 

 

Z otrzymanych danych wejściowych należy wygenerować listę „SQL-owych insertów” jako listę poszczególnych elementów  zapytania (bez białych znaków), w następującej formie: 

INSERT INTO TABLE_NAME (NAZWY PÓL) VALUES  (WARTOŚCI); 

 

Przykładowy wynik uruchomienia programu w pseudokodzie: 

LISTA<SQLINSERT>() 

 

[0] = {"INSERT", INTO","NAZWA_TABELI","(","POLE1",","," 'POLE2'"…")","VALUES","(" ,"VALUE1",",","'VALUE2'",…")",";" } 

}; 

 

LISTA<SQLINSERT>() 

 

[0] = {"INSERT","INTO","USERS","(","USERNAME", ",","AGE"…")","VALUES","(" ,"'JANEK01'",",","25",…")",";" } 

}; 

 

**  dane w buforach będa oddzielone średnikiem - ';'  

*  dane w buforach mogą zawierać więcej niż jedną linię w przypadku danych z których należy wygenerować "SQL-we inserty", jedna linia odpowiada jednemu "insertowi" 

 

Następnie należy zwrócić listę zapytań. W tym przypadku lista będzie jednoelementowa – jeden INSERT zawierający wszystkie składowe zapytania tj. INSERT, INTO … oraz średnik - ';' !!!! 

 

Input: Nazwa tabeli, typy pól w tabeli, nazwy kolumn, dane.

Output: Lista zapytań SQL INSERT, która będzie zawierała listę składowych zapytania, bez białych znaków, tak by po odseparowaniu wszystkich elementów spacją, SQL INSERT był poprawny pod względem składniowym i zakończył się powodzeniem.

 

Rozwiązanie powinno implementować interfejs ISQLConverter. Wysyłamy jeden plik kodu źródłowego zawierający tylko i wyłącznie klasę implementującą interfejs. Kolejne nadsyłane pliki będą nadpisywały poprzednie (liczy się czas ostatniego uploadu).