Prethodna tema :: Sljedeća tema |
Autor/ica |
Poruka |
krilo Forumaš(ica)
Pridružen/a: 01. 11. 2016. (14:45:48) Postovi: (4E)16
Spol:
|
|
[Vrh] |
|
krilo Forumaš(ica)
Pridružen/a: 01. 11. 2016. (14:45:48) Postovi: (4E)16
Spol:
|
Postano: 18:08 sri, 8. 2. 2017 Naslov: Brisanje elemenata niza |
|
|
Moram priznati da je vsego vrlo kreativan što se tiče zadataka u skripti :miniklap: :lol:
Zadatak kaže: Napišite program koji učitava prirodni broj n manji od 1719 i niz x od n realnih brojeva. Program treba obrisati sve elemente niza kojemu je indeks neka potencija broja 2, te ispisati novonastali niz.
Imam funkciju za prepoznavanje je li indeks potencija broja dva, ali program ne znam dovršiti. Problem je u tome što jednom kad se izvrši druga for-petlja, svi se članovi pomjere u odnosu na indekse, pa daljnja vrtnja petlje nema smisla. Palo mi je napamet početi brisati od zadnjeg člana, ali onda ne znam što na njegovo mjesto staviti; probala sam i s novom varijablom, ali ništa. :dash:
Ideje?
[code:1]int potbr2(int i)
{
int vr=1, t=i;
while (t>0) {if (t%2==0 || t==1) t/=2; else {vr=0; break;}}
if (i==0) vr=0;
return vr;
}
int main(void)
{
int n;
printf ("Unesi broj clanova niza: ");
scanf ("%d", &n);
int a[n]; int i, j, brojac=0;
printf ("Niz?: ");
for (i=0; i<n; i++) scanf ("%d", &a[i]);
for (i=1; i<n; i++)
{
if (potbr2(i)) {for (j=i; j<n; j++) a[j]=a[j+1];
brojac++; i++;}
}
n-=brojac;
for (i=0; i<n; i++) printf ("%d ", a[i]);
return 0;
}[/code:1]
Moram priznati da je vsego vrlo kreativan što se tiče zadataka u skripti
Zadatak kaže: Napišite program koji učitava prirodni broj n manji od 1719 i niz x od n realnih brojeva. Program treba obrisati sve elemente niza kojemu je indeks neka potencija broja 2, te ispisati novonastali niz.
Imam funkciju za prepoznavanje je li indeks potencija broja dva, ali program ne znam dovršiti. Problem je u tome što jednom kad se izvrši druga for-petlja, svi se članovi pomjere u odnosu na indekse, pa daljnja vrtnja petlje nema smisla. Palo mi je napamet početi brisati od zadnjeg člana, ali onda ne znam što na njegovo mjesto staviti; probala sam i s novom varijablom, ali ništa.
Ideje?
Kod: | int potbr2(int i)
{
int vr=1, t=i;
while (t>0) {if (t%2==0 || t==1) t/=2; else {vr=0; break;}}
if (i==0) vr=0;
return vr;
}
int main(void)
{
int n;
printf ("Unesi broj clanova niza: ");
scanf ("%d", &n);
int a[n]; int i, j, brojac=0;
printf ("Niz?: ");
for (i=0; i<n; i++) scanf ("%d", &a[i]);
for (i=1; i<n; i++)
{
if (potbr2(i)) {for (j=i; j<n; j++) a[j]=a[j+1];
brojac++; i++;}
}
n-=brojac;
for (i=0; i<n; i++) printf ("%d ", a[i]);
return 0;
} |
|
|
[Vrh] |
|
mdoko Forumaš(ica)
Pridružen/a: 30. 11. 2002. (22:17:12) Postovi: (71A)16
Spol:
Lokacija: Heriot-Watt University, Edinburgh
|
Postano: 19:13 sri, 8. 2. 2017 Naslov: Re: Brisanje elemenata niza |
|
|
Prva stvar, nemoj ovo raditi: [quote="krilo"][code:1]int a[n];[/code:1][/quote] Moglo bi ti odnijeti bodove na kolokviju.
Nizovi dinamičke duljine (tj. nizovi čija duljina nije odrećena prilikom kompajliranja, nego npr. unosom neke varijable) se u C-u ne deklariraju ovako. Ne bih ovdje ulazio u detalje oko toga u čemu je problem i zašto ovo ne bi trebalo raditi iako će svi kompajleri to prihvatiti.
[quote]Palo mi je napamet početi brisati od zadnjeg člana[/quote]
To je ispravan pristup.
[quote]ali onda ne znam što na njegovo mjesto staviti[/quote]
Pomakni sve članove koji se nalaze desno od onoga koji brišeš za jedno mjesto ulijevo.
Još jedna sitnica:
[quote]Imam funkciju za prepoznavanje je li indeks potencija broja dva[/quote]
Da bude sasvim jasno, nije nikakva greška protrčati po svim indeksima i za svaki od njih provjeravati radi li se o potenciji od 2. Takvo rješenje funkcionira sasvim dobro i to je ono što se očekuje od nekoga tko je tek krenuo s programiranjem.
Ipak, nije loše napomenuti da uopće ne trebaš provjeravati koji su indeksi potencije od 2. Trik je u tome umjesto trčanja po svim indeksima trčiš samo po potencijama od 2.
Kako trčati po potencijama od 2? Jednostavno: kreneš od 1 (1 = 2^0) i onda se udesno krećeš množenjem s dva, a ulijevo dijeljenjem s 2.
Kako to izgleda možeš vidjeti dolje. Probaj sama napisati program prije nego pogledaš moj kod.
[spoiler][code:1]#include <stdio.h>
int main() {
int niz[1719];
int n, d, i;
int broj_obrisanih;
printf("Duljina niza: ");
scanf("%d", &n);
for(i = 0; i < n; ++i) {
printf("niz[%d] = ", i);
scanf("%d", &niz[i]);
}
/* Trazimo najvecu potenciju od 2 koja je indeks u nasem nizu. */
d = 1; /* ovo je 2^0 */
while(d < n) { /* indeksi u nizu idu od 0 do n-1 */
d = d * 2;
}
d = d / 2; /* Gornjom petljom smo izletili iz niza, pa se moramo vratiti jedan korak unatrag */
/* Brisanje "nezeljenih" clanova niza i brojanje koliko smo ih obrisali.*/
broj_obrisanih = 0;
while(d > 0) {
/* Pocevsi od indeksa d+1, pomicemo sve clanove niza za jedno mjesto ulijevo. */
for(i = d + 1; i < n; ++i) {
niz[i-1] = niz[i];
}
broj_obrisanih = broj_obrisanih + 1;
/* Sad kad smo se rijesili elelmenta na poziciji d, mozemo krenuti brisati sljedeci element. */
d = d / 2;
}
/* Na kraju ispisemo novonastali niz. Duljina novig niza je (n - broj_obrisanih). */
for(i = 0; i < n - broj_obrisanih; ++i) {
printf("%d ", niz[i]);
}
return 0;
}[/code:1][/spoiler]
Još jedna sitnija sitnica:
U ovom kodu:
[quote][code:1]int potbr2(int i)
{
int vr=1, t=i;
while (t>0) {if (t%2==0 || t==1) t/=2; else {vr=0; break;}}
if (i==0) vr=0;
return vr;
}[/code:1][/quote]
Zašto ti treba varijabla [tt]t[/tt]?
Prva stvar, nemoj ovo raditi: Moglo bi ti odnijeti bodove na kolokviju.
Nizovi dinamičke duljine (tj. nizovi čija duljina nije odrećena prilikom kompajliranja, nego npr. unosom neke varijable) se u C-u ne deklariraju ovako. Ne bih ovdje ulazio u detalje oko toga u čemu je problem i zašto ovo ne bi trebalo raditi iako će svi kompajleri to prihvatiti.
Citat: | Palo mi je napamet početi brisati od zadnjeg člana |
To je ispravan pristup.
Citat: | ali onda ne znam što na njegovo mjesto staviti |
Pomakni sve članove koji se nalaze desno od onoga koji brišeš za jedno mjesto ulijevo.
Još jedna sitnica:
Citat: | Imam funkciju za prepoznavanje je li indeks potencija broja dva |
Da bude sasvim jasno, nije nikakva greška protrčati po svim indeksima i za svaki od njih provjeravati radi li se o potenciji od 2. Takvo rješenje funkcionira sasvim dobro i to je ono što se očekuje od nekoga tko je tek krenuo s programiranjem.
Ipak, nije loše napomenuti da uopće ne trebaš provjeravati koji su indeksi potencije od 2. Trik je u tome umjesto trčanja po svim indeksima trčiš samo po potencijama od 2.
Kako trčati po potencijama od 2? Jednostavno: kreneš od 1 (1 = 2^0) i onda se udesno krećeš množenjem s dva, a ulijevo dijeljenjem s 2.
Kako to izgleda možeš vidjeti dolje. Probaj sama napisati program prije nego pogledaš moj kod.
Spoiler [hidden; click to show]: | Kod: | #include <stdio.h>
int main() {
int niz[1719];
int n, d, i;
int broj_obrisanih;
printf("Duljina niza: ");
scanf("%d", &n);
for(i = 0; i < n; ++i) {
printf("niz[%d] = ", i);
scanf("%d", &niz[i]);
}
/* Trazimo najvecu potenciju od 2 koja je indeks u nasem nizu. */
d = 1; /* ovo je 2^0 */
while(d < n) { /* indeksi u nizu idu od 0 do n-1 */
d = d * 2;
}
d = d / 2; /* Gornjom petljom smo izletili iz niza, pa se moramo vratiti jedan korak unatrag */
/* Brisanje "nezeljenih" clanova niza i brojanje koliko smo ih obrisali.*/
broj_obrisanih = 0;
while(d > 0) {
/* Pocevsi od indeksa d+1, pomicemo sve clanove niza za jedno mjesto ulijevo. */
for(i = d + 1; i < n; ++i) {
niz[i-1] = niz[i];
}
broj_obrisanih = broj_obrisanih + 1;
/* Sad kad smo se rijesili elelmenta na poziciji d, mozemo krenuti brisati sljedeci element. */
d = d / 2;
}
/* Na kraju ispisemo novonastali niz. Duljina novig niza je (n - broj_obrisanih). */
for(i = 0; i < n - broj_obrisanih; ++i) {
printf("%d ", niz[i]);
}
return 0;
} |
|
Još jedna sitnija sitnica:
U ovom kodu:
Citat: | Kod: | int potbr2(int i)
{
int vr=1, t=i;
while (t>0) {if (t%2==0 || t==1) t/=2; else {vr=0; break;}}
if (i==0) vr=0;
return vr;
} |
|
Zašto ti treba varijabla t?
_________________ Extraordinary claims require extraordinary evidence. – Carl Sagan
|
|
[Vrh] |
|
krilo Forumaš(ica)
Pridružen/a: 01. 11. 2016. (14:45:48) Postovi: (4E)16
Spol:
|
Postano: 21:54 sri, 8. 2. 2017 Naslov: |
|
|
[quote]Moglo bi ti odnijeti bodove na kolokviju.[/quote] A kako da ga deklariram? Da deklariram niz s nekim konkretnim brojem članova, pa n unesem naknadno (i njega motam po petljama)?
[quote]Pomakni sve članove koji se nalaze desno od onoga koji brišeš za jedno mjesto ulijevo.[/quote] Ahaaaaa tek sad skužih da je to problem kad unesem n na početku... e super, to mnoga vrata otvara. :D
[quote]Zašto ti treba varijabla t?[/quote]Zato što sam napisala funkciju samo s i na početku, pa kad se izvrtila while-petlja, i je uvijek bio nula, pa i vraćena vrijednost. Tad mi je palo napamet da bi bilo dobro odvojiti slučaj i=0 i i=1.
Ova tvoja ideja je ful zanimljiva, probat ću na oba načina. :thankyou: na savjetima :D
Update: probala sam brisati niz odozada i radi k'o vurica, ali za ovaj tvoj kod nisam baš ganz sicher... Za duljinu niza unesem 10 i brojeve od 0-9, a on izbaci 0, 3, 3, 3, 5, 5 iako bi trebao maknuti samo 1, 2, 4 i 8. :tso: :kuku:
Citat: | Moglo bi ti odnijeti bodove na kolokviju. | A kako da ga deklariram? Da deklariram niz s nekim konkretnim brojem članova, pa n unesem naknadno (i njega motam po petljama)?
Citat: | Pomakni sve članove koji se nalaze desno od onoga koji brišeš za jedno mjesto ulijevo. | Ahaaaaa tek sad skužih da je to problem kad unesem n na početku... e super, to mnoga vrata otvara.
Citat: | Zašto ti treba varijabla t? | Zato što sam napisala funkciju samo s i na početku, pa kad se izvrtila while-petlja, i je uvijek bio nula, pa i vraćena vrijednost. Tad mi je palo napamet da bi bilo dobro odvojiti slučaj i=0 i i=1.
Ova tvoja ideja je ful zanimljiva, probat ću na oba načina. na savjetima
Update: probala sam brisati niz odozada i radi k'o vurica, ali za ovaj tvoj kod nisam baš ganz sicher... Za duljinu niza unesem 10 i brojeve od 0-9, a on izbaci 0, 3, 3, 3, 5, 5 iako bi trebao maknuti samo 1, 2, 4 i 8.
|
|
[Vrh] |
|
mdoko Forumaš(ica)
Pridružen/a: 30. 11. 2002. (22:17:12) Postovi: (71A)16
Spol:
Lokacija: Heriot-Watt University, Edinburgh
|
Postano: 1:06 čet, 9. 2. 2017 Naslov: |
|
|
[quote="krilo"][quote]Moglo bi ti odnijeti bodove na kolokviju.[/quote] A kako da ga deklariram? Da deklariram niz s nekim konkretnim brojem članova, pa n unesem naknadno (i njega motam po petljama)? [/quote]
Točno tako. Zato ti i je zadana maksimalna dopuštena duljina niza.
[quote][quote]Pomakni sve članove koji se nalaze desno od onoga koji brišeš za jedno mjesto ulijevo.[/quote] Ahaaaaa tek sad skužih da je to problem kad unesem n na početku... e super, to mnoga vrata otvara. :D[/quote]
Kakve veze ima veze to što unosiš [tt]n[/tt] na početku?
[quote][quote]Zašto ti treba varijabla t?[/quote]Zato što sam napisala funkciju samo s i na početku, pa kad se izvrtila while-petlja, i je uvijek bio nula, pa i vraćena vrijednost. Tad mi je palo napamet da bi bilo dobro odvojiti slučaj i=0 i i=1.[/quote]
Odlično. Onda nema nikakvih problema. Izgledalo je kao simptom jedne od čestih zabuna, ali sve je ok.
Čisto radi potpunosti diskusije, može i ovako: [code:1]int potbr2(int i)
{
int vr=1;
if (i==0) vr=0;
while (i>0) {if (i%2==0 || i==1) i/=2; else {vr=0; break;}}
return vr;
}[/code:1]
ili čak ovako: [code:1]int potbr2(int i)
{
if (i==0) return 0;
while (i>0) {if (i%2==0 || i==1) i/=2; else return 0;}
return 1;
}[/code:1]
[b]Bitna napomena:[/b] Nemoj misliti da je minimizacija broja varijabli nešto bitno. Tvoj kod je jednako efikasan kao ova moja dva. Ovdje sam ih naveo samo kako bi vidjela da je stvari moguće riješiti na više načina.
[quote]za ovaj tvoj kod nisam baš ganz sicher... Za duljinu niza unesem 10 i brojeve od 0-9, a on izbaci 0, 3, 3, 3, 5, 5 iako bi trebao maknuti samo 1, 2, 4 i 8. :tso: :kuku:[/quote]
Kako? :shock: Evo što se dogodi kad ja probam:
[code:1][mdoko@bajdo]/tmp$ cat proba.c
#include <stdio.h>
int main() {
int niz[1719];
int n, d, i;
int broj_obrisanih;
printf("Duljina niza: ");
scanf("%d", &n);
for(i = 0; i < n; ++i) {
printf("niz[%d] = ", i);
scanf("%d", &niz[i]);
}
/* Trazimo najvecu potenciju od 2 koja je indeks u nasem nizu. */
d = 1; /* ovo je 2^0 */
while(d < n) { /* indeksi u nizu idu od 0 do n-1 */
d = d * 2;
}
d = d / 2; /* Gornjom petljom smo izletili iz niza, pa se moramo vratiti jedan korak unatrag */
/* Brisanje "nezeljenih" clanova niza i brojanje koliko smo ih obrisali.*/
broj_obrisanih = 0;
while(d > 0) {
/* Pocevsi od indeksa d+1, pomicemo sve clanove niza za jedno mjesto ulijevo. */
for(i = d + 1; i < n; ++i) {
niz[i-1] = niz[i];
}
broj_obrisanih = broj_obrisanih + 1;
/* Sad kad smo se rijesili elelmenta na poziciji d, mozemo krenuti brisati sljedeci element. */
d = d / 2;
}
/* Na kraju ispisemo novonastali niz. Duljina novig niza je (n - broj_obrisanih). */
for(i = 0; i < n - broj_obrisanih; ++i) {
printf("%d ", niz[i]);
}
return 0;
}
[mdoko@bajdo]/tmp$ gcc -o proba -O1 -std=c89 -pedantic-errors -Wall -Wextra -Wno-unused-result proba.c
[mdoko@bajdo]/tmp$ ./proba
Duljina niza: 10
niz[0] = 0
niz[1] = 1
niz[2] = 2
niz[3] = 3
niz[4] = 4
niz[5] = 5
niz[6] = 6
niz[7] = 7
niz[8] = 8
niz[9] = 9
0 3 5 6 7 9[/code:1]
Meni se čini da radi kako treba. :neznam:
krilo (napisa): | Citat: | Moglo bi ti odnijeti bodove na kolokviju. | A kako da ga deklariram? Da deklariram niz s nekim konkretnim brojem članova, pa n unesem naknadno (i njega motam po petljama)? |
Točno tako. Zato ti i je zadana maksimalna dopuštena duljina niza.
Citat: | Citat: | Pomakni sve članove koji se nalaze desno od onoga koji brišeš za jedno mjesto ulijevo. | Ahaaaaa tek sad skužih da je to problem kad unesem n na početku... e super, to mnoga vrata otvara. |
Kakve veze ima veze to što unosiš n na početku?
Citat: | Citat: | Zašto ti treba varijabla t? | Zato što sam napisala funkciju samo s i na početku, pa kad se izvrtila while-petlja, i je uvijek bio nula, pa i vraćena vrijednost. Tad mi je palo napamet da bi bilo dobro odvojiti slučaj i=0 i i=1. |
Odlično. Onda nema nikakvih problema. Izgledalo je kao simptom jedne od čestih zabuna, ali sve je ok.
Čisto radi potpunosti diskusije, može i ovako: Kod: | int potbr2(int i)
{
int vr=1;
if (i==0) vr=0;
while (i>0) {if (i%2==0 || i==1) i/=2; else {vr=0; break;}}
return vr;
} |
ili čak ovako: Kod: | int potbr2(int i)
{
if (i==0) return 0;
while (i>0) {if (i%2==0 || i==1) i/=2; else return 0;}
return 1;
} |
Bitna napomena: Nemoj misliti da je minimizacija broja varijabli nešto bitno. Tvoj kod je jednako efikasan kao ova moja dva. Ovdje sam ih naveo samo kako bi vidjela da je stvari moguće riješiti na više načina.
Citat: | za ovaj tvoj kod nisam baš ganz sicher... Za duljinu niza unesem 10 i brojeve od 0-9, a on izbaci 0, 3, 3, 3, 5, 5 iako bi trebao maknuti samo 1, 2, 4 i 8. |
Kako? Evo što se dogodi kad ja probam:
Kod: | [mdoko@bajdo]/tmp$ cat proba.c
#include <stdio.h>
int main() {
int niz[1719];
int n, d, i;
int broj_obrisanih;
printf("Duljina niza: ");
scanf("%d", &n);
for(i = 0; i < n; ++i) {
printf("niz[%d] = ", i);
scanf("%d", &niz[i]);
}
/* Trazimo najvecu potenciju od 2 koja je indeks u nasem nizu. */
d = 1; /* ovo je 2^0 */
while(d < n) { /* indeksi u nizu idu od 0 do n-1 */
d = d * 2;
}
d = d / 2; /* Gornjom petljom smo izletili iz niza, pa se moramo vratiti jedan korak unatrag */
/* Brisanje "nezeljenih" clanova niza i brojanje koliko smo ih obrisali.*/
broj_obrisanih = 0;
while(d > 0) {
/* Pocevsi od indeksa d+1, pomicemo sve clanove niza za jedno mjesto ulijevo. */
for(i = d + 1; i < n; ++i) {
niz[i-1] = niz[i];
}
broj_obrisanih = broj_obrisanih + 1;
/* Sad kad smo se rijesili elelmenta na poziciji d, mozemo krenuti brisati sljedeci element. */
d = d / 2;
}
/* Na kraju ispisemo novonastali niz. Duljina novig niza je (n - broj_obrisanih). */
for(i = 0; i < n - broj_obrisanih; ++i) {
printf("%d ", niz[i]);
}
return 0;
}
[mdoko@bajdo]/tmp$ gcc -o proba -O1 -std=c89 -pedantic-errors -Wall -Wextra -Wno-unused-result proba.c
[mdoko@bajdo]/tmp$ ./proba
Duljina niza: 10
niz[0] = 0
niz[1] = 1
niz[2] = 2
niz[3] = 3
niz[4] = 4
niz[5] = 5
niz[6] = 6
niz[7] = 7
niz[8] = 8
niz[9] = 9
0 3 5 6 7 9 |
Meni se čini da radi kako treba.
_________________ Extraordinary claims require extraordinary evidence. – Carl Sagan
|
|
[Vrh] |
|
krilo Forumaš(ica)
Pridružen/a: 01. 11. 2016. (14:45:48) Postovi: (4E)16
Spol:
|
|
[Vrh] |
|
mdoko Forumaš(ica)
Pridružen/a: 30. 11. 2002. (22:17:12) Postovi: (71A)16
Spol:
Lokacija: Heriot-Watt University, Edinburgh
|
|
[Vrh] |
|
krilo Forumaš(ica)
Pridružen/a: 01. 11. 2016. (14:45:48) Postovi: (4E)16
Spol:
|
Postano: 13:04 čet, 9. 2. 2017 Naslov: Zadatak iz kolokvija |
|
|
Drugi kolokvij, zadatak 2. 2016. Polje C sastoji se od n znakova. Svaki od tih znakova je ili ’!’ (rub), ili ’x’ (križić), ili ’o’ (kružić). Područje između dva susjedna ruba zovemo igra. Prvi i zadnji znak u polju su rubovi. Niti jedna igra nije prazna, tj. u svakoj postoji barem jedan križić ili kružić. Na primjer, ako je n = 12, a polje C je kao na donjoj slici, onda postoje 3 igre, u prvoj imamo 2 križića i 1 kružić, u drugoj 1 križić i 1 kružić, a u trećoj su 2 kružića i 1 križić. (Izgled polja: !xox!xo!xoo!)
(a) Napišite funkciju broji koja prima polje C i prirodni broj n, te vraća ukupan broj igara, ukupan broj križića i ukupan broj kružića u polju C. Možete koristiti “varijabilne argumente”.
(b) U svakoj igri u kojoj ima više križića nego kružića, pobjeđuje križić, i sve kružiće u toj igri zamjenjuje križićem. Analogno, u svakoj igri u kojoj ima više kružića nego križića, pobjeđuje kružić, i sve križiće u toj igri zamjenjuje kružićem. Napišite funkciju igra koja prima polje C i prirodni broj n, te mijenja polje C tako da ono odražava situaciju nakon određivanja tko je pobijedio. Na primjer, ako je na ulazu polje C bilo kao na slici gore, onda na izlazu iz funkcije ono treba izgledati ovako: !xxx!xo!ooo!
Funkcija pod a) napisana i radi, ali ova pod b) neće pa neće. Probala sam valjda petsto puta s međuispisima, ali jednostavno ne mogu naći razlog zašto se petlja s [tt]j[/tt], kad je [tt]i[/tt] najveći mogući, vrti u nedogled. :bluescreen: :???:
[code:1]void prebroji (char a[], int n, int *krizic, int *kruzic, int *igre)
{
*krizic=0; *kruzic=0; *igre=-1;
int i;
for (i=0; i<n; i++)
{
if (a[i]=='o') (*kruzic)++;
if (a[i]=='!') (*igre)++;
if (a[i]=='x') (*krizic)++;
}
}
void igra(char a[], int n)
{
int i, j, s, r;
for (i=0; i<n;)
{
for (j=i+1; j; j++) {if (a[j]=='!') break;}
int krizic=0, kruzic=0, igre=0, k;
for (k=i+1; k<j; k++)
{
if (a[k]=='o') (kruzic)++;
if (a[k]=='x') (krizic)++;
}
if(krizic>kruzic) {for(s=i+1; s<j; s++) a[s]='x';}
if(kruzic>krizic) {for(s=i+1; s<j; s++) a[s]='o';}
i=j;
}
for (i=0; i<n; i++) printf ("%c", a[i]);
}
int main(void)
{
char a[20]; int i, n, krizic, kruzic, igre;
printf ("Duljina niza? ");
scanf ("%d", &n);
printf ("Niz? ");
for (i=0; i<n; i++) scanf (" %c", &a[i]);
prebroji(a,n,&krizic,&kruzic,&igre);
printf ("Krizica: %d\nKruzica: %d\nIgara: %d\n", krizic, kruzic, igre);
igra(a,n);
return 0;
}[/code:1]
Drugi kolokvij, zadatak 2. 2016. Polje C sastoji se od n znakova. Svaki od tih znakova je ili ’!’ (rub), ili ’x’ (križić), ili ’o’ (kružić). Područje između dva susjedna ruba zovemo igra. Prvi i zadnji znak u polju su rubovi. Niti jedna igra nije prazna, tj. u svakoj postoji barem jedan križić ili kružić. Na primjer, ako je n = 12, a polje C je kao na donjoj slici, onda postoje 3 igre, u prvoj imamo 2 križića i 1 kružić, u drugoj 1 križić i 1 kružić, a u trećoj su 2 kružića i 1 križić. (Izgled polja: !xox!xo!xoo!)
(a) Napišite funkciju broji koja prima polje C i prirodni broj n, te vraća ukupan broj igara, ukupan broj križića i ukupan broj kružića u polju C. Možete koristiti “varijabilne argumente”.
(b) U svakoj igri u kojoj ima više križića nego kružića, pobjeđuje križić, i sve kružiće u toj igri zamjenjuje križićem. Analogno, u svakoj igri u kojoj ima više kružića nego križića, pobjeđuje kružić, i sve križiće u toj igri zamjenjuje kružićem. Napišite funkciju igra koja prima polje C i prirodni broj n, te mijenja polje C tako da ono odražava situaciju nakon određivanja tko je pobijedio. Na primjer, ako je na ulazu polje C bilo kao na slici gore, onda na izlazu iz funkcije ono treba izgledati ovako: !xxx!xo!ooo!
Funkcija pod a) napisana i radi, ali ova pod b) neće pa neće. Probala sam valjda petsto puta s međuispisima, ali jednostavno ne mogu naći razlog zašto se petlja s j, kad je i najveći mogući, vrti u nedogled.
Kod: | void prebroji (char a[], int n, int *krizic, int *kruzic, int *igre)
{
*krizic=0; *kruzic=0; *igre=-1;
int i;
for (i=0; i<n; i++)
{
if (a[i]=='o') (*kruzic)++;
if (a[i]=='!') (*igre)++;
if (a[i]=='x') (*krizic)++;
}
}
void igra(char a[], int n)
{
int i, j, s, r;
for (i=0; i<n;)
{
for (j=i+1; j; j++) {if (a[j]=='!') break;}
int krizic=0, kruzic=0, igre=0, k;
for (k=i+1; k<j; k++)
{
if (a[k]=='o') (kruzic)++;
if (a[k]=='x') (krizic)++;
}
if(krizic>kruzic) {for(s=i+1; s<j; s++) a[s]='x';}
if(kruzic>krizic) {for(s=i+1; s<j; s++) a[s]='o';}
i=j;
}
for (i=0; i<n; i++) printf ("%c", a[i]);
}
int main(void)
{
char a[20]; int i, n, krizic, kruzic, igre;
printf ("Duljina niza? ");
scanf ("%d", &n);
printf ("Niz? ");
for (i=0; i<n; i++) scanf (" %c", &a[i]);
prebroji(a,n,&krizic,&kruzic,&igre);
printf ("Krizica: %d\nKruzica: %d\nIgara: %d\n", krizic, kruzic, igre);
igra(a,n);
return 0;
} |
|
|
[Vrh] |
|
Mala_022 Forumaš(ica)
Pridružen/a: 21. 01. 2006. (18:15:12) Postovi: (73)16
Spol:
Lokacija: ...evo mene među moje...
|
Postano: 14:11 čet, 9. 2. 2017 Naslov: Re: Zadatak iz kolokvija |
|
|
[quote="krilo"]Probala sam valjda petsto puta s međuispisima, ali jednostavno ne mogu naći razlog zašto se petlja s [tt]j[/tt], kad je [tt]i[/tt] najveći mogući, vrti u nedogled. :bluescreen: :???:[/quote]
Samo ukratko (dok ne dođe mdoko :wink: ) - kad je [tt]i[/tt] najveći mogući ([tt]i=n-1[/tt]), onda je [tt]j=i+1=n[/tt], a ne znamo šta je [tt]a[n][/tt] (i onda još u petlji povećavaš [tt]j[/tt] bez provjeravanja dokle uopće može ići).
krilo (napisa): | Probala sam valjda petsto puta s međuispisima, ali jednostavno ne mogu naći razlog zašto se petlja s j, kad je i najveći mogući, vrti u nedogled. |
Samo ukratko (dok ne dođe mdoko ) - kad je i najveći mogući (i=n-1), onda je j=i+1=n, a ne znamo šta je a[n] (i onda još u petlji povećavaš j bez provjeravanja dokle uopće može ići).
|
|
[Vrh] |
|
mdoko Forumaš(ica)
Pridružen/a: 30. 11. 2002. (22:17:12) Postovi: (71A)16
Spol:
Lokacija: Heriot-Watt University, Edinburgh
|
Postano: 17:08 čet, 9. 2. 2017 Naslov: Re: Zadatak iz kolokvija |
|
|
[quote="Mala_022"][quote="krilo"]Probala sam valjda petsto puta s međuispisima, ali jednostavno ne mogu naći razlog zašto se petlja s [tt]j[/tt], kad je [tt]i[/tt] najveći mogući, vrti u nedogled. :bluescreen: :???:[/quote]
Samo ukratko (dok ne dođe mdoko :wink: ) - kad je [tt]i[/tt] najveći mogući ([tt]i=n-1[/tt]), onda je [tt]j=i+1=n[/tt], a ne znamo šta je [tt]a[n][/tt] (i onda još u petlji povećavaš [tt]j[/tt] bez provjeravanja dokle uopće može ići).[/quote]
Čini se da može i bez mene. :wink:
Mala_022 (napisa): | krilo (napisa): | Probala sam valjda petsto puta s međuispisima, ali jednostavno ne mogu naći razlog zašto se petlja s j, kad je i najveći mogući, vrti u nedogled. |
Samo ukratko (dok ne dođe mdoko ) - kad je i najveći mogući (i=n-1), onda je j=i+1=n, a ne znamo šta je a[n] (i onda još u petlji povećavaš j bez provjeravanja dokle uopće može ići). |
Čini se da može i bez mene.
_________________ Extraordinary claims require extraordinary evidence. – Carl Sagan
|
|
[Vrh] |
|
krilo Forumaš(ica)
Pridružen/a: 01. 11. 2016. (14:45:48) Postovi: (4E)16
Spol:
|
Postano: 18:04 čet, 9. 2. 2017 Naslov: |
|
|
E sad sam pravo zbunjena... :zbunjen:
Generalno, algoritam je ovakav: jot je indeks prvog sljedećeg uskličnika, pa se prema omjeru križića i kružića situacija mijenja u "ogradi". Poslije mijenjanja, [tt]i[/tt] postaje jot i isti se postupak dalje nastavlja.
Poanta je u tome da [tt]i[/tt] nije jednak [tt]n-1[/tt] (barem ne u testnom primjeru). Tu bi zadnji mogući [tt]i[/tt] trebao biti na 8. mjestu (na trećem uskličniku), pa bi [tt]j[/tt] (sljedeći nađeni uskličnik) trebao biti na 12 mjestu. Na kraju for-petlje imamo [tt]i=j[/tt], a kako je [tt]j=12[/tt] trebala bi se for-petlja uredno prekinuti. (Tako da se ne bi desio slučaj [tt]j=n[/tt].)
Ispravite me ako griješim, al stvarno ne znam di griješim :kuku: :gaah:
E sad sam pravo zbunjena...
Generalno, algoritam je ovakav: jot je indeks prvog sljedećeg uskličnika, pa se prema omjeru križića i kružića situacija mijenja u "ogradi". Poslije mijenjanja, i postaje jot i isti se postupak dalje nastavlja.
Poanta je u tome da i nije jednak n-1 (barem ne u testnom primjeru). Tu bi zadnji mogući i trebao biti na 8. mjestu (na trećem uskličniku), pa bi j (sljedeći nađeni uskličnik) trebao biti na 12 mjestu. Na kraju for-petlje imamo i=j, a kako je j=12 trebala bi se for-petlja uredno prekinuti. (Tako da se ne bi desio slučaj j=n.)
Ispravite me ako griješim, al stvarno ne znam di griješim
|
|
[Vrh] |
|
Mala_022 Forumaš(ica)
Pridružen/a: 21. 01. 2006. (18:15:12) Postovi: (73)16
Spol:
Lokacija: ...evo mene među moje...
|
Postano: 19:20 čet, 9. 2. 2017 Naslov: |
|
|
[quote="krilo"]Generalno, algoritam je ovakav: jot je indeks prvog sljedećeg uskličnika, pa se prema omjeru križića i kružića situacija mijenja u "ogradi". Poslije mijenjanja, [tt]i[/tt] postaje jot i isti se postupak dalje nastavlja.
Poanta je u tome da [tt]i[/tt] nije jednak [tt]n-1[/tt] (barem ne u testnom primjeru). Tu bi zadnji mogući [tt]i[/tt] trebao biti na 8. mjestu (na trećem uskličniku), pa bi [tt]j[/tt] (sljedeći nađeni uskličnik) trebao biti na 12 mjestu. Na kraju for-petlje imamo [tt]i=j[/tt], a kako je [tt]j=12[/tt] trebala bi se for-petlja uredno prekinuti. (Tako da se ne bi desio slučaj [tt]j=n[/tt].)
Ispravite me ako griješim, al stvarno ne znam di griješim :kuku: :gaah:[/quote]
[quote="krilo"][code:1]
void igra(char a[], int n)
{
int i, j, s, r;
for (i=0; i<n;) <----------
{
for (j=i+1; j; j++){if (a[j]=='!') break;} <----------
int krizic=0, kruzic=0, igre=0, k;
for (k=i+1; k<j; k++)
{
if (a[k]=='o') (kruzic)++;
if (a[k]=='x') (krizic)++;
}
if(krizic>kruzic) {for(s=i+1; s<j; s++) a[s]='x';}
if(kruzic>krizic) {for(s=i+1; s<j; s++) a[s]='o';}
i=j;
}
for (i=0; i<n; i++) printf ("%c", a[i]);
}
[/code:1][/quote]
U testnom primjeru je n=12, [tt]i[/tt] ide [tt]0-11[/tt]! Na početku je [tt]i=0[/tt], prvi sljedeći uskličnik je za [tt]j=4[/tt] pa postane [tt]i=4[/tt], onda ide [tt]i=j=7[/tt] i dotle je OK. Onda krene od [tt]j=8[/tt] i nastavlja dalje, dođe do [tt]j=11[/tt] i postavi [tt]i=11[/tt]. Ti u petlji dopuštaš da se petlja vrti dokle god je [tt]i<n[/tt] (prva strelica u kodu), a 11<12, tako da je uvjet i dalje zadovoljen, petlja se ne prekida, nego nastavlja izvršavanje za [tt]j=i+1=12[/tt] (druga strelica u kodu).
krilo (napisa): | Generalno, algoritam je ovakav: jot je indeks prvog sljedećeg uskličnika, pa se prema omjeru križića i kružića situacija mijenja u "ogradi". Poslije mijenjanja, i postaje jot i isti se postupak dalje nastavlja.
Poanta je u tome da i nije jednak n-1 (barem ne u testnom primjeru). Tu bi zadnji mogući i trebao biti na 8. mjestu (na trećem uskličniku), pa bi j (sljedeći nađeni uskličnik) trebao biti na 12 mjestu. Na kraju for-petlje imamo i=j, a kako je j=12 trebala bi se for-petlja uredno prekinuti. (Tako da se ne bi desio slučaj j=n.)
Ispravite me ako griješim, al stvarno ne znam di griješim |
krilo (napisa): | Kod: |
void igra(char a[], int n)
{
int i, j, s, r;
for (i=0; i<n;) <----------
{
for (j=i+1; j; j++){if (a[j]=='!') break;} <----------
int krizic=0, kruzic=0, igre=0, k;
for (k=i+1; k<j; k++)
{
if (a[k]=='o') (kruzic)++;
if (a[k]=='x') (krizic)++;
}
if(krizic>kruzic) {for(s=i+1; s<j; s++) a[s]='x';}
if(kruzic>krizic) {for(s=i+1; s<j; s++) a[s]='o';}
i=j;
}
for (i=0; i<n; i++) printf ("%c", a[i]);
}
|
|
U testnom primjeru je n=12, i ide 0-11! Na početku je i=0, prvi sljedeći uskličnik je za j=4 pa postane i=4, onda ide i=j=7 i dotle je OK. Onda krene od j=8 i nastavlja dalje, dođe do j=11 i postavi i=11. Ti u petlji dopuštaš da se petlja vrti dokle god je i<n (prva strelica u kodu), a 11<12, tako da je uvjet i dalje zadovoljen, petlja se ne prekida, nego nastavlja izvršavanje za j=i+1=12 (druga strelica u kodu).
|
|
[Vrh] |
|
krilo Forumaš(ica)
Pridružen/a: 01. 11. 2016. (14:45:48) Postovi: (4E)16
Spol:
|
|
[Vrh] |
|
|