SPOJ VSR- prędkość średnia.

0

Witajcie,

raczkuję dopiero i proszę o wyrozumiałość.
Po obejrzeniu lekcji 12 Mirka Zelenta, dot SPOJ'a postanowiłem zrobić sam program polegający na funkcji (staram się ogarniać funkcje, żeby kod był przejrzystszy). Problem w tym, że nie mogę namierzyć gdzie robię błąd, ponieważ wyrzuca mi tylko jedną wartość średniej zamiast dwóch... Próbowałem już różnych iteracji i ta jest jedną z najbardziej sensownych jakie mi wychodziły.

Za każdą radę będę wdzięczny x)

# include <iostream>
using namespace std;

int srednia_predkosc(int predkosc_1, int predkosc_2, int liczba_zestawow_danych)
{

    int wynik=0;

    cin >> liczba_zestawow_danych;

    for (int i=0; i < liczba_zestawow_danych; i++)
    {
        wynik = 2*predkosc_1*predkosc_2 /(predkosc_1+predkosc_2);
        //cout << wynik << endl;

    }
    return wynik;
}
int main ()
{
    int ilosc_razy;
    int predkosc1, predkosc2;
    int srednia = 0;

    cout << "podaj ilosc razy jaka ma byc wykonana: " << endl;
    cin >> ilosc_razy;

    cout << "podaj predkosci po spacji: " << endl;
    cin >> predkosc1 >> predkosc2;

    srednia = srednia_predkosc(predkosc1,predkosc2,ilosc_razy);

    cout << srednia << endl;
    return 0;
}
4

Radziłbym najpierw zacząć bez funkcji.
Bo nie wiesz co czynisz:

  1. w main() wczytujesz ilosc_razy oraz dwie prędkości po czym w funkcji jeszcze raz wczytujesz ilosc_razy nazwaną jako liczba_zestawow_danych WTF?
  2. jak ilosc_razy będzie wynosić 100 to ile razy wczytają się dwie prędkości, czy nie powinno być właśnie 100?
  3. na SPOJ powinieneś zacząć od zadania testowego, aby zrozumiałeś że to cout << "podaj... już jest błędem
#include <iostream>
using namespace std;

int main()
  {
   unsigned T,A,B;
   for(cin>>T;T--;cout<<(2*A*B/(A+B))<<endl) cin>>A>>B;
   return 0;
  }
2

@RdoG:

Zagadka, jaka będzie zwykła średnia z liczb 2 i 3 gdy liczyć na liczbach całkowitych

_13th_Dragon napisał(a):

Radziłbym najpierw zacząć bez funkcji.
Bo nie wiesz co czynisz:

W 100% się zgadzam. Sposób zbudowania argumentów funkcji świadczy, że jest j/w

GDYBY ewentualnie chodziło o dane powtarzalne o zmiennej liczności, należało by użyć tablicy

RdoG napisał(a):

Po obejrzeniu lekcji 12 Mirka Zelenta,

To nazwisko jest tu sławne ... ale jak sądzisz, że z dobrej strony ... to nie, wręcz przeciwnie.
A są miejsca, że gość udowadnia swoją niewiedzę. Ma tylko parcie na szkło.

0
_13th_Dragon napisał(a):

Radziłbym najpierw zacząć bez funkcji.
Bo nie wiesz co czynisz:

  1. w main() wczytujesz ilosc_razy oraz dwie prędkości po czym w funkcji jeszcze raz wczytujesz ilosc_razy nazwaną jako liczba_zestawow_danych WTF?
  2. jak ilosc_razy będzie wynosić 100 to ile razy wczytają się dwie prędkości, czy nie powinno być właśnie 100?
  3. na SPOJ powinieneś zacząć od zadania testowego, aby zrozumiałeś że to cout << "podaj... już jest błędem
#include <iostream>
using namespace std;

int main()
  {
   unsigned T,A,B;
   for(cin>>T;T--;cout<<(2*A*B/(A+B))<<endl) cin>>A>>B;
   return 0;
  }

Jak zrobię wszystko w main'ie bez funkcji, to działa jak tralalala.
Po prostu nie ogarniam jeszcze działania funkcji i próbuje je robić, a jak nie wychodzi to pytam.
W każdym razie dzięki za tipa, zaraz to będę zmieniać :)

0

W funkcji zwracasz 1 liczbe, musiałbyś zwrócić kolekcje intow np. List<int> a wcześniej do resultu dodać te 2 liczby

0

Ok,
po Waszych radach udało mi się dojść do tego co robię źle...

finalny kod oparty na funkcjach :

int liczenie_sredniej(int predkosc1, int predkosc2, int ilosc_razy)
{
    int wynik = 0;
    
    for (int i = 0; i < ilosc_razy; i++)
    {
        wynik = 2*predkosc1*predkosc2/(predkosc1+predkosc2);

    }
    return wynik;
}
int main()
{
    int rakieta1, rakieta2, liczba_razy;
    int srednia = 0;

    cin >> liczba_razy;

    for (int i = 0; i < liczba_razy; i++)
    {

        cin >> rakieta1 >> rakieta2;

        srednia = liczenie_sredniej(rakieta1,rakieta2,liczba_razy);

        cout << srednia << endl;
    }

    return 0;

}

BTW, w jaki sposób sformatować / wstawić mój kod był tutaj tak jak w przypadku @_13th_Dragon: ?
Skoro Zelent nie ma zbyt dobrego rozgłosu, to z jakich źródeł powinienem korzystać najlepiej?

Pozdr.

0

Każdą średnią wystarczy obliczyć tylko raz!
Po kiego liczysz ją wielokrotnie w pętli?

0
_13th_Dragon napisał(a):

Każdą średnią wystarczy obliczyć tylko raz!
Po kiego liczysz ją wielokrotnie w pętli?

Ponieważ inaczej nie wykonuje mi się tyle razy ile dałem :V.
Czyli suma sumarum dalej jest źle skoro przez SPOJ'a przeszło..?

0

Jaka wartość zostanie zwrócona w następnych 4ch przypadkach?
Która z nich najszybsza a która najwolniejsza? Czemu?:

//1.
return 2+3;
//2.
int x=2+3;
return x;
//3.
int x=0;
x=2+3;
x=2+3;
x=2+3;
return x;
//4.
int x=0;
for(int i=0;i<1000000;++i) x=2+3;
return x;
0
_13th_Dragon napisał(a):

Jaka wartość zostanie zwrócona w następnych 4ch przypadkach?
Która z nich najszybsza a która najwolniejsza? Czemu?:

//1.
return 2+3;
//2.
int x=2+3;
return x;
//3.
int x=0;
x=2+3;
x=2+3;
x=2+3;
return x;
//4.
int x=0;
for(int i=0;i<1000000;++i) x=2+3;
return x;

Wartość równa 5.

najszybsza pierwsza, najwolniejsza ostatnia.
Pierwsza ponieważ zwracasz od strzała wynik, a ostatnia najwolniej bo musi przemielić przez całą pętle.

Dobrze rozumuje?

0
RdoG napisał(a):

Dobrze rozumuje?

Tak, dobrze rozumiesz, z tym że ja nie rozumiem czemu w kodzie zastosowałeś wersje 4?

0

Tak, dobrze rozumiesz, z tym że ja nie rozumiem czemu w kodzie zastosowałeś wersje 4?

Ponieważ się uczę i nie ogarniam jeszcze funkcji, a chcę już je implementować :V.

Wywaliłem pętle w funkcji i zostawiłem w main'ie...

int liczenie_sredniej(int predkosc1, int predkosc2)
{
    int wynik = 0;

    wynik = 2*predkosc1*predkosc2/(predkosc1+predkosc2);

    return wynik;
}
int main()
{
    int rakieta1, rakieta2, liczba_razy;
    int srednia = 0;

    cin >> liczba_razy;

    for (int i = 0; i < liczba_razy; i++)
    {

        cin >> rakieta1 >> rakieta2;

        srednia = liczenie_sredniej(rakieta1,rakieta2);

        cout << srednia << endl;
    }

    return 0;

}

Myślę że o to Ci chodziło x)

0

Nie! Mówisz że 1-sza szybsza zaś 4-tą zmieniłeś na 3-cią.

1
RdoG napisał(a):

Jak zrobię wszystko w main'ie bez funkcji, to działa jak tralalala.
Po prostu nie ogarniam jeszcze działania funkcji i próbuje je robić, a jak nie wychodzi to pytam.
W każdym razie dzięki za tipa, zaraz to będę zmieniać :)

W jakimś sensie użycie funkcji stało się celem, a nie jest, zawsze jest środkiem do czegoś.

Dlatego jak zawsze przywiększym kodzie udziela się porad "wydziel funkcję" - a tu, ku mojemu zaskoczeniu, a słusznie @_13th_Dragon doradził: nie używaj funkcji.

Funkcji się używa, aby wydzielić jakiś kod, czy to używany wielokrotnie (bez tego musiał by być kopiowany), czy tworzący pewną zamknieta całość (przy okazji dając mu - zaskakująco ważne - dobrą nazwę)

Problem w tym wątku jest taki, że płaszczyzna cięcia jest nieokreslona / nieczysta. Tak jakby w restauracji / barze - gdzie normalnie jest cięcie na zaplecze (kuchnię) i przód - surowce były na sali z klientami. Bardzo nieszczęśliwa granica, już nie tylko "schabowy z kapustą raz" , ale "daj trochę ziemniaków"
Miarą złego podzielenia jest, że trzeba przekazywać nienaturalnie za dużo i kółko (te ziemniaki)

Uzdrawiające w tym wątku by było, określenie zadania tej funkcji, jej celu, co robi i CZEGO NIE ROBI. Np

  • procesuje jeden zestaw danych od wczytania do wydrukowania (logika by szybko wskazała, ze argument ilość zestawów jest zbędny). Wtedy dobrą nzwą by było procesuj_jeden_zestaw()
  • oblicza jeden zestaw danych (średnią) - ale nie drukuje licz_srednia()
  • inny zdrowy podział, z jasnymi obowiazkami - i jasnym "nie"
  • jeśli funckja na dobra nazwę - czyli nie kłamie w/s tego co robi - to jest jedna czynność, jeden czasownik, a nie zestaw czasowników połączony i
    Wtedy podział na funkcje byłby udany.
1

Może jako przykład tego co piszę @ZrobieDobrze wszak lepiej jeden raz zobaczyć niż siedem raz usłyszeć.
Totalnie ekstremalny podział, ale całkiem sensowny:

#include <iostream>
using namespace std;

unsigned readValue()
{
	unsigned value;
	cin>>value;
	return value;
}

unsigned averageVelocity(unsigned vA,unsigned vB) { return 2*vA*vB/(vA+vB); }

void proceedTest() { cout<<averageVelocity(readValue(),readValue())<<endl; }

void proceedTests(unsigned count) { while(count--) proceedTest(); }

int main()
{
	proceedTests(readValue());
	return 0;
}
2
RdoG napisał(a):

Po obejrzeniu lekcji 12 Mirka Zelenta, dot SPOJ'a
....

....
int main ()
{
    ......

    cout << "podaj ilosc razy jaka ma byc wykonana: " << endl;
    cin >> ilosc_razy;

    cout << "podaj predkosci po spacji: " << endl;
    cin >> predkosc1 >> predkosc2;

    srednia = srednia_predkosc(predkosc1,predkosc2,ilosc_razy);

    cout << srednia << endl;
    return 0;
}

Robisz podstawowy błąd przy rozwiązywaniu dowolnego zadania na SPOJ lub dowolnie innej stronie tego typu.
Wypisujesz rzeczy, które nie są oczekiwane!
Treść zadania zawsze wyraźnie specyfikuje co masz wypisywać. Automat sprawdzający wynik, zgłosi złą odpowiedź jeśli natrafi na cokolwiek co nie pasuje do specyfikacju zadania.
Dlatego wszelkie zachęty do wpisywania danych przez użytkownika: "podaj ilosc razy jaka ma byc wykonana: " doprowadza do odrzucenia rozwiązania przez automatycznego sędziego.

1

@_13th_Dragon: uuu, implementation defined behaviour się wkradło (aczkolwiek, przypadkiem nie ma znaczenia).
Mianowicie, kolejność ewaluacji obu readValue nie jest określona, i GCC zrobi to na odwrót niż clang.

0
enedil napisał(a):

... aczkolwiek, przypadkiem nie ma znaczenia ...

Nie przypadkiem - zrobiono tak bo nie ma znaczenia. Poza tym to łatwo się przerabia w variadic template nie chciałem nastraszać początkującego.

1 użytkowników online, w tym zalogowanych: 0, gości: 1