Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

Lekcja 2.21 - zadanie 2 (losowanie bez powtórzeń)

Ostatnio zmodyfikowano 2016-08-12 09:07
Autor Wiadomość
jundymek
Temat założony przez niniejszego użytkownika
Lekcja 2.21 - zadanie 2 (losowanie bez powtórzeń)
» 2016-08-11 20:10:18
Chciałem prosić o sprawdzenie poprawności kodu. Męczyłem się strasznie i niestety nie do końca rozumiem cały kod. Ten C++ jest strasznie zakręcony w porównaniu do pythona. Poniżej daję do porównania to samo zadanie rozwiązane w Pythonie...

C/C++
#include <iostream>
#include <cstdlib>
#include <ctime>

using namespace std;

int podajLiczby( int tablica[] )
{
    int liczba;
    int i = 0;
    for( int i = 0; i < 10; i++ )
    { cout << "Podaj " << i + 1 << " liczbe: ";
        cin >> liczba;
        tablica[ i ] = liczba;
    }
}


int losoweLiczby()
{
    int index;
    index =( rand() % 8 );
    //cout << tablica[index]<< endl;}
    return index;
}

bool czyBylaWylosowana( int liczba, int tab[], int ile )
{
    if( ile <= 0 )
         return false;
   
    int i = 0;
    do
    {
        if( tab[ i ] == liczba )
             return true;
       
        i++;
    } while( i < ile );
   
    return false;
}

int main()
{
    srand( time( 0 ) );
    int tablica[ 10 ];
    int tab[ 8 ];
    int liczba;
    int index;
    int wylosowanych = 0;
    podajLiczby( tablica );
    //cout << tablica[1];
   
    //wypiszLiczby(tablica, 3);
   
    while( wylosowanych < 8 )
    {
        index = losoweLiczby();
        liczba = tablica[ index ];
        if( czyBylaWylosowana( liczba, tab, wylosowanych ) == false )
        {
            tab[ wylosowanych ] = liczba;
            cout << tab[ wylosowanych ] << endl;
            wylosowanych++;
        }
    }
   
   
    return 0;
}


#!/usr/bin/env python
# -*- coding: utf-8 -*-

import random


def wczytaj(lista):
    for i in range(10):
        print 'Podaj {} liczbę: '.format(i + 1),
        liczba = raw_input()
        lista.append(int(liczba))


def losuj(lista2):
    while (len(lista2) < 8):
        x = random.randint(0, 9)
        if lista[x] not in lista2:
            lista2.append(lista[x])

lista = []
lista2 = []
wczytaj(lista)
losuj(lista2)
for i in lista2:
    print i
P-150747
kistel66
» 2016-08-11 21:40:36
A czego konkretnie nie rozumiesz? Ciężko pomóc, jak nie wiadomo o co chodzi.
P-150748
carlosmay
» 2016-08-11 21:56:22
C/C++
int podajLiczby( int tablica[] )
Zapamiętaj, że jak zawracasz coś z funkcji, wtedy funkcja ta powinna być takiego typu jak zwracana wartość.
W przeciwnym wypadku (jak tutaj) nic nie zwracasz więc funkcja powinna być typu
void
.

C/C++
while( wylosowanych < 8 )
Nie używaj magicznych liczb, bo nic nie mówią.
Zamiast nich deklaruj zmienne, o wymownych nazwach.
C/C++
while( wylosowanych < rozmiazTablicyWylosowanych )
 i wszystko jasne.

Nadawaj sensowne nazwy zmiennym.

To takie pierwsze rzucające się w oczy niedociągnięcia.
P-150749
jundymek
Temat założony przez niniejszego użytkownika
» 2016-08-11 21:58:18
A czego konkretnie nie rozumiesz? Ciężko pomóc, jak nie wiadomo o co chodzi.

Największy problem miałem z ogarnięciem sprawdzania wylosowanych liczb.  Muszę jeszcze to na spokojnie przeanalizować. Ogólnie w tym całym C++ kod jest strasznie rozwleczony i sprawia mi trudność poskładania wszystkiego w jedną całość. Pozostaje pisać i próbować dalej.

C/C++
bool czyBylaWylosowana( int liczba, int tab[], int ile )
{
    //if (ile<=0)
    //return false;
    int i = 0;
    do
    {
        if( tab[ i ] == liczba )
             return true;
       
        i++;
    } while( i < ile );
   
    return false;
}
P-150750
Monika90
» 2016-08-11 22:10:13
C++ jest jak Python tylko szybsze 50 razy
C/C++
#include <iostream>
#include <algorithm>
#include <vector>
#include <random>

auto wczytaj() {
    std::vector < int > lista;
    for( int i = 0; i < 10; ++i ) {
        std::cout << "Podaj " << i + 1 << " liczbe: ";
        int liczba;
        std::cin >> liczba;
        lista.push_back( liczba );
    }
   
    return lista;
}

auto losuj( const std::vector < int >& lista ) {
    std::mt19937 urbg( std::random_device { }() );
    std::uniform_int_distribution < int > d( 0, lista.size() - 1 );
    std::vector < int > wylosowane;
    while( wylosowane.size() < 8 ) {
        const auto liczba = lista[ d( urbg ) ];
        if( std::find( wylosowane.begin(), wylosowane.end(), liczba ) == wylosowane.end() )
             wylosowane.push_back( liczba );
       
    }
   
    return wylosowane;
}

void wypisz( const std::vector < int >& lista ) {
    for( const auto & liczba: lista )
         std::cout << liczba << '\n';
   
}

int main() {
    wypisz( losuj( wczytaj() ) );
}
P-150752
jundymek
Temat założony przez niniejszego użytkownika
» 2016-08-11 23:06:07
C++ jest jak Python tylko szybsze 50 razy
50 razy szybszy w działaniu, 50 razy (no dobra - 2;)) wolniejszy w pisaniu. C++ postanowiłem spróbować za namową Mirosława Zelenta. Proponował na początek naukę C++ i po obejrzeniu paru jego filmików stwierdziłem, że spróbuję. Ja zaczynałem od Pythona, ale tak naprawdę cały czas próbuję załapać podstawy programowania. Zauważyłem jednak, że prawdą jest, że jak nauczy się jednego języka to później jest już dużo prościej. Moja nawet pobieżna znajomość Pythona daje naprawdę sporo jak próbuję walczyć z C++. Twój kod to czarna magia jak na razie. Faktycznie skrócony, ale za dużo nowych rzeczy na raz...
P-150754
mateczek
» 2016-08-11 23:11:09

Twój kod to czarna magia jak na razie.
Pani Monika jest zaawansowaną programistką c++.  Mocno wykorzystuje STL, c++11 i algorytmy. Dlatego kod może wydawać się trudny do zrozumienia, dla kogoś kto dopiero zaczyna i przerobił tylko kusy podstawowe (pętle,funkcje, struktury, podstawy klass). Więc na spokojnie. I nie przejmuj się kodu nie kumasz:P. Na początek zapoznaj się z kontenerami STL-a, używaniem szablonów w c++, poczytaj o gotowych algorytmach biblioteki stl.

Mirosława Zelenta.
Gość ma fajne kursy. Jednak osądzanie, że język c++ jest dobry na początek jest trochę niedocenianiem c++ przez pana Zelenta. Język C++ jest pełen subtelności, i rozwija się ciągle. Więc jak zaczniesz "na początek" do przez kupę lat będziesz miał się czego uczyć (zagłębianie się w niuanse bibliotek to zabawa na długi, długi czas):P

Wracając do tematu losowania bez powtórzeń. Jak pokombinujesz to możesz po prostu kasować wylosowany element listy !!! co jeszcze bardziej skróci kod!!!
C/C++
#include <iostream>
#include<vector>                           //kontener koniecznie zapoznaj się z podstawowymi kontenerami
#include<ctime>
#include<random>
using namespace std;

int main() {
    srand( time( 0 ) );
    vector < int > lista { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 }; //kontener zamiast tablicy!!!. pomiędzy nawiasami"<>" podajesz jakiego typu(jakiej klasy) elementy ma przechowywać
    for( int i = 0; i < 8; i++ ) //osiem losowań
    {
        int index = rand() % lista.size(); //losowanie indexu
        cout << lista[ index ] << " "; //wyświetlenie wylosowanego elementu. W c++ klasa może mieć przeładowane operatory. Dlatego lista[] wygląda jak zwykła tablica!!!
        lista.erase( lista.begin() + index ); //usuwanie wylosowanego elementu. I kolejne losowanie odbywa się już z jego pominięciem
    }
   
}
P-150755
Elaine
» 2016-08-12 09:07:20
std::mt19937 urbg( std::random_device { }() );
C/C++
boost::random::random_device rd;
std::mt19937 urbg( rd );
FTFY. Takie użycie std::random_device nie jest w niczym lepsze od seedowania z std::time(nullptr). Niestety, std::random_device ma dość bezużyteczny interfejs i nie stanowi seed sequence.

Mersenne Twister to osobny problem, ale ani w bibliotece standardowej, ani w booście nie ma nic lepszego, więc to pominę.
P-150761
« 1 »
  Strona 1 z 1