Przekształć poniższy kod aby zwracał liczby (i wypisał ich czynniki ) takie, które mają trzy różne czynniki nieparzyste. np. 1157625: 3, 3, 3, 5, 5, 5, 7, 7, 7 TAK; 105: 3, 5, 7 TAK; 1287: 3, 3, 11, 13 TAK; 3465: 3, 3, 5, 7, 11 NIE
Bardzo proszę o dobre odpowiedzi, odpowiedzi tylko dla punktów będą zgłaszane. Jest to trudne zadanie, dlatego daje każdemu, kto dobrze zrobi 30 punktów. Z góry dziekuję.
Program, który napisałam znajdziesz w pierwszych dwóch załącznikach.
Trzeci załącznik zawiera plik tekstowy z przykładowego uruchomienia dla liczb z zakresu od 105, do 999999.
Wyjaśnienie
Niestety właściwie nie było co przekształcać z tego co wrzuciłeś. Zostawiłam z oryginału tylko oznaczenie n dla zmiennej będącej końcem zakresu i użycie cin oraz cout. (Jak może zauważyłeś preferuję printf, ale akurat w tym przypadku nawet przejrzyściej jest użyć cout. :) Zwykle nie jest... )
Mam sporo komentarzy do swojego programu i dużo uwag do Twojego...
Zacznę od Twojego. Zrób sobie i tym, którzy będą czytali Twoje programy tę przyjemność, że nazwy zmiennych będą opisowe, a jednoliterowe zostawisz w miejscach, gdzie ma to sens (np. czasami pętle). Funkcja sprawdzająca powinna zwracać True / False, wtedy od razu warunek jest oczywisty, tutaj if w wierszu 35.
Problem, nawet gdy jest bardzo łatwy, warto (a czasem należy) rozłożyć na elementy. W przypadku tego zadania minimalny podział na moduły uznałam, że jest następujący:
wyznaczenie górnego zakresu obliczeń + pętla przechodząca przez cały zakres od początku (oczywiście nie od 2, tylko od 105) do końca (n czytane z konsoli);
sprawdzenie czy liczba ma dokładnie trzy różne czynniki i wydrukowanie czynników jeśli spełnia ten warunek;
funkcja pomocnicza sprawdzająca czy czynnikiem x jest y – tak, doskonale wiem, że ( x % y == 0 ) – ale moim zdaniem takie wyodrębnienie polepsza czytelność kodu, a i sprawdzenie dzielenia przez 0 nie jest przypadkowe (choć akurat w tym programie rzeczywiście bezużyteczne, możesz pominąć);
funkcja pomocnicza sprawdzająca, czy liczba jest pierwsza.
Podejrzewam, że nie na darmo poprzednie zadanie dotyczyło wyznaczenia tablicy liczb pierwszych! Użycie takiej tablicy istotnie przyspieszyłoby działanie tego programu. Czyli powinna być funkcja tworząca tablicę liczb pierwszych aż do n, a funkcja czyLiczbaPierwsza() tylko by sprawdzała w tej tablicy i już nic nie wyliczała.
Zapewne należałoby też wydzielić z funkcji czynniki3() wypisywanie wyniku. Jednak popatrzyłam na Twoje programy i zdecydowałam, że zbyt dużo modułów mogłoby Tobie dać wrażenie skomplikowanego programu. I tak płynnie przeszłam do komentowania swojego programu. :)
Pisanie zaczęłam od zdecydowania w jakiej strukturze będę przechowywała informację o tym, które trzy czynniki oraz ile razy każdy z nich. Można by użyć tablicy 3x2. Ale byłoby to dosyć skomplikowane ponieważ nie tylko trzeba by sprawdzać czy coś zostało już zapisane, ale i też nieźle nagimnastykować się z tym gdzie co zapisać. A jest to po prostu typowe zadanie dla tablicy asocjacyjnej, mapy (C++), słownika (w wielu innych językach programowania). Dalej już było łatwo.
Na samym początku sprawdzam czy badana liczba nie jest przypadkiem liczbą pierwszą. Sprawdzenie tego właśnie na samym początku uprościło mi logikę dalszego kodu.
O... właśnie zauważyłam błąd... Pętla powinna sprawdzać od 3, co 2, a nie co 1 – ale to już sobie sam poprawisz.
Tak więc czynniki3() zawiera pętlę, która po kolei sprawdza liczby pierwsze mniejsze od połowy szukanej liczby czy są czynnikami. Jeśli któraś liczba pierwsza jest czynnikiem, to w pętli sprawdzane jest ile razy. W tym momencie nie jest sprawdzane czy liczba miała tylko jeden czynnik, czy dwa, a może trzy. Ale przy (tzn. po) dodaniu kolejnego czynnika jest sprawdzane czy przypadkiem nie jest to już czwarty czynnik. Jeżeli jest, to wtedy zakres pętli jest zmieniany na 0 i pętla już dalej nie będzie wykonywana. (Tak, można zmieniać parametry pętli.)
Natomiast drukowane będą czynniki tylko wtedy gdy są dokładnie trzy czynniki.
Ponieważ zadanie wymaga oddzielenia czynników przecinkami i spacjami, bezpośrednio po każdym czynniku dodaję przecinek i spację. Miałabym więc po ostatnim czynniku zbędne przecinek i spację... Zamieniam je na znak nowej linii. Właśnie tak. Na pewno nie należy użyć endl.
Nie wiem jak szybki masz komputer, ale nie próbowałabym początkowo zakresu szerszego niż od 105, do około 50000 (50 tysięcy).
2 votes Thanks 1
0AB
A co konkretnie ma być prościej? ? ? Żadnych trików nie robiłam...
Pętla "for" w wierszu 58 jest do zapamiętania, że tak się zawsze robi gdy jest w C++ struktura "map". Taka pętla przechodzi po kolei przez cały "map" (który zawsze jest posortowany). Klucz jest dostępny jako .first, a wartość jako .second.
0AB
Dodatkowo, specjalnie aby było zrozumiale, na początku wypisałam skąd się co wzięło. Potem gdy już będziesz i tak wiedział, też będzie takie wypisywanie się przydawało aby mieć listę użytych funkcji.
Alanoblog9
chodzi o poziom licealny 1 klasa, korzystając tylko z bibliotek iostream i cmath
Alanoblog9
program rozumiem, tylko wszystkie kolejne programy musiałbym pisać na takim poziomie , a jeszcze nie mam takiej wiedzy
Alanoblog9
A skąd masz taką wiedzę? (chętnie bym się nauczył, bo mamy okropnego nauczyciela)
0AB
Bez string można, ale będzie bardziej skomplikowanie i mniej elegancko. A w dodatku program będzie wyraźnie wolniej działał. Dlatego nawet nie komentowałam dlaczego podjęłam decyzję o użyciu string.
Natomiast wprawdzie tak jak napisałam, map jest naturalne w tego typu pytaniach, ale jednak jeśli potrzebujesz, to mogę napisać nowy program bez map. Daj nowe zadanie za minimalną ilość punktów. Możesz do do niego skopiować opis z tego, ale dokładnie opisz, że nie mogą być map i string itd.
Odpowiedź
Program, który napisałam znajdziesz w pierwszych dwóch załącznikach.
Trzeci załącznik zawiera plik tekstowy z przykładowego uruchomienia dla liczb z zakresu od 105, do 999999.
Wyjaśnienie
Niestety właściwie nie było co przekształcać z tego co wrzuciłeś. Zostawiłam z oryginału tylko oznaczenie n dla zmiennej będącej końcem zakresu i użycie cin oraz cout. (Jak może zauważyłeś preferuję printf, ale akurat w tym przypadku nawet przejrzyściej jest użyć cout. :) Zwykle nie jest... )
Mam sporo komentarzy do swojego programu i dużo uwag do Twojego...
Zacznę od Twojego. Zrób sobie i tym, którzy będą czytali Twoje programy tę przyjemność, że nazwy zmiennych będą opisowe, a jednoliterowe zostawisz w miejscach, gdzie ma to sens (np. czasami pętle). Funkcja sprawdzająca powinna zwracać True / False, wtedy od razu warunek jest oczywisty, tutaj if w wierszu 35.
Problem, nawet gdy jest bardzo łatwy, warto (a czasem należy) rozłożyć na elementy. W przypadku tego zadania minimalny podział na moduły uznałam, że jest następujący:
Podejrzewam, że nie na darmo poprzednie zadanie dotyczyło wyznaczenia tablicy liczb pierwszych! Użycie takiej tablicy istotnie przyspieszyłoby działanie tego programu. Czyli powinna być funkcja tworząca tablicę liczb pierwszych aż do n, a funkcja czyLiczbaPierwsza() tylko by sprawdzała w tej tablicy i już nic nie wyliczała.
Zapewne należałoby też wydzielić z funkcji czynniki3() wypisywanie wyniku. Jednak popatrzyłam na Twoje programy i zdecydowałam, że zbyt dużo modułów mogłoby Tobie dać wrażenie skomplikowanego programu. I tak płynnie przeszłam do komentowania swojego programu. :)
Pisanie zaczęłam od zdecydowania w jakiej strukturze będę przechowywała informację o tym, które trzy czynniki oraz ile razy każdy z nich. Można by użyć tablicy 3x2. Ale byłoby to dosyć skomplikowane ponieważ nie tylko trzeba by sprawdzać czy coś zostało już zapisane, ale i też nieźle nagimnastykować się z tym gdzie co zapisać. A jest to po prostu typowe zadanie dla tablicy asocjacyjnej, mapy (C++), słownika (w wielu innych językach programowania). Dalej już było łatwo.
Na samym początku sprawdzam czy badana liczba nie jest przypadkiem liczbą pierwszą. Sprawdzenie tego właśnie na samym początku uprościło mi logikę dalszego kodu.
O... właśnie zauważyłam błąd... Pętla powinna sprawdzać od 3, co 2, a nie co 1 – ale to już sobie sam poprawisz.
Tak więc czynniki3() zawiera pętlę, która po kolei sprawdza liczby pierwsze mniejsze od połowy szukanej liczby czy są czynnikami. Jeśli któraś liczba pierwsza jest czynnikiem, to w pętli sprawdzane jest ile razy. W tym momencie nie jest sprawdzane czy liczba miała tylko jeden czynnik, czy dwa, a może trzy. Ale przy (tzn. po) dodaniu kolejnego czynnika jest sprawdzane czy przypadkiem nie jest to już czwarty czynnik. Jeżeli jest, to wtedy zakres pętli jest zmieniany na 0 i pętla już dalej nie będzie wykonywana. (Tak, można zmieniać parametry pętli.)
Natomiast drukowane będą czynniki tylko wtedy gdy są dokładnie trzy czynniki.
Ponieważ zadanie wymaga oddzielenia czynników przecinkami i spacjami, bezpośrednio po każdym czynniku dodaję przecinek i spację. Miałabym więc po ostatnim czynniku zbędne przecinek i spację... Zamieniam je na znak nowej linii. Właśnie tak. Na pewno nie należy użyć endl.
Nie wiem jak szybki masz komputer, ale nie próbowałabym początkowo zakresu szerszego niż od 105, do około 50000 (50 tysięcy).
Pętla "for" w wierszu 58 jest do zapamiętania, że tak się zawsze robi gdy jest w C++ struktura "map".
Taka pętla przechodzi po kolei przez cały "map" (który zawsze jest posortowany).
Klucz jest dostępny jako .first, a wartość jako .second.
Natomiast wprawdzie tak jak napisałam, map jest naturalne w tego typu pytaniach, ale jednak jeśli potrzebujesz, to mogę napisać nowy program bez map. Daj nowe zadanie za minimalną ilość punktów. Możesz do do niego skopiować opis z tego, ale dokładnie opisz, że nie mogą być map i string itd.