C++¶
Implementacja¶
#include <iostream>
#include "maja.h"
void resetuj(bool kandydaci[]) {
for(int i = 0; i <= 1000000; i++) {
kandydaci[i] = true;
}
}
void odznaczNiep(bool kandydaci[], int wiel) {
for(int i = wiel; i <= 1000000; i += wiel) {
kandydaci[i] = false;
}
}
void odznaczPodz(bool kandydaci[], int wiel) {
for(int i = 1; i <= 1000000; i++) {
if(i % wiel != 0) {
kandydaci[i] = false;
}
}
}
int main() {
int n;
bool kandydaci[1000001];
n = gramy_dalej();
while(n != 0) {
resetuj(kandydaci);
for(int i = 2; i <= n; i++) {
if(kandydaci[i]) {
if(!czy_podzielna_przez(i)) {
odznaczNiep(kandydaci, i);
} else {
odznaczPodz(kandydaci, i);
}
}
}
for(int i = 1; i <= n; i++) {
if(kandydaci[i]) {
zgaduj(i);
break;
}
}
n = gramy_dalej();
}
return 0;
}
Opis¶
Funkcja resetuj
wypełnia tablicę kandydaci
wartościami true
.
Funkcja odznaczNiep
skreśla z tablicy wszystkie wielokrotności podanej wartości wiel
.
Funkcja odznaczPodz
skreśla z tablicy wszystkie liczby, które nie są wielokrotnością podanej wartości wiel
.
W tablicy kandydaci
przechowujemy informacje na temat potencjalnych wartości, o których mogła pomyśleć Maja.
Jeżeli pod indeksem \(i\) w tablicy znajduje się wartość true
, to znaczy że liczba \(i\) może wciąż być prawidłową odpowiedzią.
Jeżeli natomiast pod indeksem \(i\) znajduje się wartość false
, oznacza to, że liczba \(i\) została skreślona, więc wiemy już, że nie jest prawidłową odpowiedzią.
Na początku działania programu wywołujemy funkcję gramy_dalej
, której wynik zapisujemy w zmiennej n
, w ten sposób poznając górne ograniczenie dla zgadywanej wartości. Następnie w pętli powtarzamy operacje tak długo, aż otrzymamy \(n=0\), co oznacza koniec danych wejściowych.
Na początku pętli, przed przystąpieniem do odpytywania o podzielność, resetujemy tablicę kandydatów (linia 31), korzystając z pomocniczej funkcji resetuj
. Następnie przechodzimy przez wszystkie wartości od \(2\) do górnego ograniczenia przedziału \(n\) włącznie (linia 33).
Dla każdej wartości sprawdzamy, czy nie została ona jeszcze skreślona w tablicy kandydatów, to znaczy czy może być poprawną odpowiedzią (linia 34).
Jeżeli tak jest, to odpytujemy o podzielność przez tę właśnie liczbę za pomocą funkcji czy_podzielna_przez
(linia 35).
Jeżeli szukana liczba nie jest podzielna przez \(i\) to w tablicy kandydatów skreślamy wszystkie wielokrotności \(i\) (linia 36) korzystając z pomocniczej funkcji odznaczNiep
.
W przeciwnym przypadku, tzn. gdy szukana wartość jest podzielna przez \(i\) to skreślamy wszystkie wartości niepodzielne przez \(i\) (linia 38) za pomocą pomocniczej funkcji odznaczPodz
.
Gdy już przejdziemy przez wszystkie wartości ze sprawdzanego zakresu i zadamy wszystkie sensowne pytania o podzielność, możemy przystąpić do odgadnięcia szukanej liczby. W tym celu musimy znaleźć w tablicy kandydatów wartość, która nie została jeszcze skreślona. Przechodzimy więc pętlą przez wszystkie potencjalne wartości od \(1\) do \(n\) włącznie (linia 43) i dla każdej sprawdzamy, czy nie została ona skreślona (linia 44). Gdy znajdziemy taką wartość, dokonujemy próby odgadnięcia (linia 45) i wychodzimy z pętli ( linia 46).
Na koniec rozpoczynamy kolejną rozgrywkę za pomocą funkcji gramy_dalej
pobierając górne ograniczenie przedziału (linia 51).