Biedrzyk Temat założony przez niniejszego użytkownika |
[c++] Zadanie SPOJ JLITOSL - Liczba na słowo » 2020-02-17 21:02:47 Witam, zabrałem się za zadnie ze SPOJ-a JLITOSL - Liczba na słowo, https://pl.spoj.com/problems/JLITOSL/. Jaś zaczął pracować w dziale firmy odpowiedzialnym za finanse. Do jego codziennych obowiązków należy wypełnianie przelewów pocztowych za różnego rodzaju płatności. Po kilku dniach zaczął odczuwać zniechęcenie, gdy po raz setny musiał na przelewie wypisywać słownie kwotę. Pomoż Jasiowi i napisz program, który będzie zamieniał liczbę na jej zapis słowny. Wejście W pierwszym wierszu podana jest liczba testów t do wykonania (liczba naturalna z przedziału 1..1000). W następnych t wierszach liczba naturalna z przedziału 1..1012. Wyjście Na wyjściu powinny być wyświetlane w osobnych wierszach odpowiedniki liczb naturalnych podanych na wejściu w zapisie słownym (w wyrazach nie używamy polskich znaków). W zapisie należy użyć następujących skrótów: tys. - tysiąc, mln. - milion, mld. - miliard, bln. - bilion. Przykład Wejście: 5 1 12 345 1459 123456789 Wyjście: jeden dwanascie trzysta czterdziesci piec jeden tys. czterysta piecdziesiat dziewiec sto dwadziescia trzy mln. czterysta piecdziesiat szesc tys. siedemset osiemdziesiat dziewiec Kombinuję z mapą i na razie stoję w tym miejscu - jestem dopiero przy tysiącach a już liczba if'ów jest już duża a gdzie mi jeszcze do większych liczb. Pytanie czy jednak da się to trochę ulepszyć - nie chcę przeginać i zapętlić się w tych ifach. #include <iostream> #include <string> #include <map>
using namespace std;
int dziesiatki( int liczba ) { liczba =(( liczba / 10 ) * 10 ); return liczba; }
int setki( int liczba ) { liczba =(( liczba / 100 ) * 100 ); return liczba; }
int tysiace( int liczba ) { liczba =( liczba / 1000 ); return liczba; }
int main() { map < int, string >::reverse_iterator ritr; map < int, string > inWords; inWords[ 0 ] = "zero"; inWords[ 1 ] = "jeden"; inWords[ 2 ] = "dwa"; inWords[ 3 ] = "trzy"; inWords[ 4 ] = "cztery"; inWords[ 5 ] = "piec"; inWords[ 6 ] = "szesc"; inWords[ 7 ] = "siedem"; inWords[ 8 ] = "osiem"; inWords[ 9 ] = "dziewiec"; inWords[ 10 ] = "dziesiec"; inWords[ 11 ] = "jedenascie"; inWords[ 12 ] = "dwanascie"; inWords[ 13 ] = "trzynascie"; inWords[ 14 ] = "czternascie"; inWords[ 15 ] = "pietnascie"; inWords[ 16 ] = "szesnascie"; inWords[ 17 ] = "siedemnascie"; inWords[ 18 ] = "osiemnascie"; inWords[ 19 ] = "dziewietnascie"; inWords[ 20 ] = "dwadziescia"; inWords[ 30 ] = "trzydziesci"; inWords[ 40 ] = "czterdziesci"; inWords[ 50 ] = "piecdziesiat"; inWords[ 60 ] = "szczescdziesiat"; inWords[ 70 ] = "siedemdziesiat"; inWords[ 80 ] = "osiemdziesiat"; inWords[ 90 ] = "dziewiecdziesiat"; inWords[ 100 ] = "sto"; inWords[ 200 ] = "dwiescie"; inWords[ 300 ] = "trzysta"; inWords[ 400 ] = "czterysta"; inWords[ 500 ] = "piecset"; inWords[ 600 ] = "szescset"; inWords[ 700 ] = "siedemset"; inWords[ 800 ] = "osiemset"; inWords[ 900 ] = "dziewiecset"; int liczba = 0, nowa = 0, mniejsza = 0, nowa2 = 0, mniejsza2 = 0, nowa3 = 0, mniejsza3 = 0; cin >> liczba; for( map < int, string >::reverse_iterator ritr = inWords.rbegin(); ritr != inWords.rend(); ritr++ ) { if( liczba == ritr->first ) { cout << ritr->second; } if(( liczba > 20 ) &&( liczba < 100 ) &&( liczba != ritr->first ) ) { mniejsza = dziesiatki( liczba ); nowa = liczba % 10; if( nowa == ritr->first ) { cout << ritr->second << " "; } if( mniejsza == ritr->first ) { cout << ritr->second << " "; } } if(( liczba > 100 ) &&( liczba < 1000 ) &&( liczba != ritr->first ) ) { mniejsza2 = setki( liczba ); nowa3 = liczba - mniejsza2; nowa2 = dziesiatki( nowa3 ); mniejsza3 = nowa3 - nowa2; if( nowa2 == ritr->first ) { cout << ritr->second << " "; } if( mniejsza2 == ritr->first ) { cout << ritr->second << " "; } if( nowa3 == ritr->first ) { cout << ritr->second << " "; } if( mniejsza3 == ritr->first ) { cout << ritr->second << " "; } } if(( liczba >= 1000 ) &&( liczba <= 1000000 ) &&( liczba != ritr->first ) ) { mniejsza =( liczba / 1000 ); nowa = liczba - mniejsza; if( mniejsza == ritr->first ) { cout << ritr->second << " " << "tys."; } } } return 0; }
|
|
mizie |
Propozycja » 2020-02-18 10:19:26 Mam nadzieję, że poniższy kod przyda ci się w szukaniu własnego rozwiązania. Zaznaczam, że moja jest tylko implementacja z wykorzystaniem mapy, o którą pytasz. Źródło pomysłu na algorytm (opartego na tablicach) podane jest w komentarzu na początku kodu. #include <iostream> #include <string> #include <map> #include <random> using std::string; using std::cout; using std::cin; using std::endl;
const std::map < short, string > liczby_slownie = { { 0, "" }, { 1, " jeden" }, { 2, " dwa" }, { 3, " trzy" }, { 4, " cztery" }, { 5, " piec" }, { 6, " szesc" }, { 7, " siedem" }, { 8, " osiem" }, { 9, " dziewiec" }, { 10, " dziesiec" }, { 11, " jedenascie" }, { 12, " dwanascie" }, { 13, " trzynascie" }, { 14, " czternascie" }, { 15, " pietnascie" }, { 16, " szesnascie" }, { 17, " siedemnascie" }, { 18, " osiemnascie" }, { 19, " dziewietnascie" }, { 20, " dwadziescia" }, { 30, " trzydziesci" }, { 40, " czterdziesci" }, { 50, " piecdziesiat" }, { 60, " szescdziesiat" }, { 70, " siedemdziesiat" }, { 80, " osiemdziesiat" }, { 90, " dziewiecdziesiat" }, { 100, " sto" }, { 200, " dwiescie" }, { 300, " trzysta" }, { 400, " czterysta" }, { 500, " piecset" }, { 600, " szescset" }, { 700, " siedemset" }, { 800, " osiemset" }, { 900, " dziewiecset" } }; const string magnitude[ 5 ] = { "", " tys.", " mln.", " mld.", " bln." };
int main() { cout << "Podaj ilosc liczb (od 1 do 1000), ktore chcesz zapisac slownie: "; int i { 0 }; if( !( cin >> i ) || i < 1 || i > 1000 ) { cout << "Bledne dane.\n"; system( "PAUSE" ); return 1; } std::random_device rd; std::default_random_engine dre( rd() ); std::uniform_int_distribution < long long > dist( 1, 1000000000000 ); while( i > 0 ) { long long x { 0 }, temp { 0 }; x = dist( dre ); temp = x; string slownie = ""; int itm { 0 }, j { 0 }, koncowka { 0 }; if( x == 0 ) slownie = "zero"; while( x > 0 ) { koncowka = x % 10; x /= 10; if(( j == 0 ) &&( x % 100 != 0 || koncowka != 0 ) ) slownie.insert( 0, magnitude[ itm ] ); if(( j == 0 ) &&( x % 10 != 1 ) ) slownie.insert( 0, liczby_slownie.find( koncowka )->second ); if(( j == 0 ) &&( x % 10 == 1 ) ) { slownie.insert( 0, liczby_slownie.find( koncowka + 10 )->second ); x /= 10; j += 2; continue; } if( j == 1 ) slownie.insert( 0, liczby_slownie.find( koncowka * 10 )->second ); if( j == 2 ) { slownie.insert( 0, liczby_slownie.find( koncowka * 100 )->second ); j = - 1; if( itm < 5 ) ++itm; } ++j; } std::cout << temp << " to: " << slownie << "\n"; --i; } system( "PAUSE" ); return 0; }
|
|
Biedrzyk Temat założony przez niniejszego użytkownika |
» 2020-02-18 13:43:13 Dzięki za podpowiedź, będę kombinował. |
|
Biedrzyk Temat założony przez niniejszego użytkownika |
» 2020-02-23 13:28:47 Dopiero po kilku dniach znów mogłem zasiąść do zadania i na razie doszedłem do tego: #include <iostream> #include <string> #include <map>
using namespace std;
int main() { map < int, string >::reverse_iterator ritr; map < int, string > inWords; inWords[ 1 ] = "jeden"; inWords[ 2 ] = "dwa"; inWords[ 3 ] = "trzy"; inWords[ 4 ] = "cztery"; inWords[ 5 ] = "piec"; inWords[ 6 ] = "szesc"; inWords[ 7 ] = "siedem"; inWords[ 8 ] = "osiem"; inWords[ 9 ] = "dziewiec"; inWords[ 10 ] = "dziesiec"; inWords[ 11 ] = "jedenascie"; inWords[ 12 ] = "dwanascie"; inWords[ 13 ] = "trzynascie"; inWords[ 14 ] = "czternascie"; inWords[ 15 ] = "pietnascie"; inWords[ 16 ] = "szesnascie"; inWords[ 17 ] = "siedemnascie"; inWords[ 18 ] = "osiemnascie"; inWords[ 19 ] = "dziewietnascie"; inWords[ 20 ] = "dwadziescia"; inWords[ 30 ] = "trzydziesci"; inWords[ 40 ] = "czterdziesci"; inWords[ 50 ] = "piecdziesiat"; inWords[ 60 ] = "szczescdziesiat"; inWords[ 70 ] = "siedemdziesiat"; inWords[ 80 ] = "osiemdziesiat"; inWords[ 90 ] = "dziewiecdziesiat"; inWords[ 100 ] = "sto"; inWords[ 200 ] = "dwiescie"; inWords[ 300 ] = "trzysta"; inWords[ 400 ] = "czterysta"; inWords[ 500 ] = "piecset"; inWords[ 600 ] = "szescset"; inWords[ 700 ] = "siedemset"; inWords[ 800 ] = "osiemset"; inWords[ 900 ] = "dziewiecset"; int liczba = 0; int mnoznik = 10, wynik = 0; int * pomoc; pomoc = new int[ mnoznik ]; cin >> liczba; for( map < int, string >::reverse_iterator ritr = inWords.rbegin(); ritr != inWords.rend(); ritr++ ) { if( liczba == ritr->first ) { cout << ritr->second; } if(( liczba > 20 ) &&( liczba != ritr->first ) ) { do { wynik = liczba % mnoznik; liczba = liczba - wynik; mnoznik *= 10; for( map < int, string >::reverse_iterator ritr = inWords.rbegin(); ritr != inWords.rend(); ritr++ ) { if( wynik == ritr->first ) { cout << ritr->second << " "; } if( liczba == ritr->first ) { cout << ritr->second << " "; } if(( wynik >= 1000 ) &&( wynik < 1000000 ) ) { wynik /= 1000; cout << "tys."; } if(( wynik >= 1000000 ) &&( wynik < 1000000000 ) ) { wynik /= 1000000; cout << "mln."; } if(( wynik >= 1000000000 ) &&( wynik < 1000000000000 ) ) { wynik /= 1000000000; cout << "mld."; } if(( wynik >= 1000000000000 ) &&( wynik < 1000000000000000 ) ) { wynik /= 1000000000000; cout << "bln."; } } } while(( wynik > 0 ) &&( liczba > 0 ) ); } return 0; } }
program gubi się przy liczbach pełnych tj. 12000000, odczytuje od tyłu liczbę( co rozumiem bo odcina kolejne liczby i musi porównać z mapą). Teraz najlepiej by było w pierwszej kolejności odwrócić kolejność odczytywanych liczb a potem zająć się odczytywaniem pełnych liczb - prosiłbym o podpowiedź. |
|
pekfos |
» 2020-02-23 14:13:47 Ta mapa jest tu bardziej utrudnieniem niż pomocą. Napisz funkcję, która generuje zapis słowny liczby z zakresu [0; 1000). Do tego wystarczą 3 tablice na look-up słów dla cyfr na pozycjach setek, dziesiątek i jedności. Potem to już tylko "X milionów Y tysięcy Z". Look-up ma zawsze charakter pomocniczy w konstrukcji algorytmu. Zaczynanie od mapy wartości jako od "łatwiejszej części" to budowanie piramidy zaczynając od góry. Sensowne tablice pomocnicze do tego zadania mają klucze z przedziału [0; 9] co jest zadaniem dla tablicy, nie mapy. Indeksowanie w tablicy znacznie szybsze od wyszukiwania w mapie, a Ty nawet nie używasz wyszukiwania, tylko jeszcze wolniejszego iterowania po niej. |
|
Biedrzyk Temat założony przez niniejszego użytkownika |
» 2020-02-23 19:42:29 Dzięki, spróbuję pójść w tym kierunku. |
|
Biedrzyk Temat założony przez niniejszego użytkownika |
» 2020-03-11 00:05:04 Kod mam już gotowy ale pojawił się mały problem - przekształca mi ładnie liczby na słowa, ale gdy przyszło do stworzenia pętli to niejako dopisuje mi kolejne wprowadzane stringi :/ wiem, że trzeba wyzerować stringa, ale próbowałem już z clear, ignore, sync, po prostu liczba = ""; ale nie dało to żadnego efektu np. wpisuję 2 dostaję dwa potem wpisuję 5 i dostaję pięć tys. dwa. Wstawiam kod z pastebina https:pastebin.comvvwm0UqU |
|
nanoant20 |
» 2020-03-11 15:05:24 w linku który podałeś zabrakło "/" po .com D czyść kontener vector w pętli for( int i = 0; i < iloscTestow; i++ ) { cin >> liczba; podajSlownyZapisLiczbyTrzycyfrowej( liczba, liczby ); liczby.clear(); }
|
|
« 1 » 2 |