Co zrobić z tą pętlą?

0

Mam banalny dla doświadczonych programistów problem. W następującym programie:

#include <cstdlib>
#include <iostream>
#include <map>

using namespace std;

map<int,int> CheckOccurrence (int X[], int Size, int Key)
{
    map<int,int> RetMap;
    int Cntr = 1;

    for(int i = 0; i < Size; ++i)
        if( X[i] == Key )
            RetMap[Cntr++] = i;
    RetMap[0] = Cntr-1;

    return RetMap;
}

int main()
{
    int TestArray[180] = { 
3,10,11,14,22,23,32,35,43,     44,6,9,16,19,24,29,37,38,45,48,  2,5,13,18,25,30,31,40,41,0,
2,5,16,19,25,30,34,39,45,48,   1,9,12,13,21,24,33,36,44,49,     3,8,15,20,23,26,35,40,43,46,
6,9,13,20,28,29,33,40,43,48,   2,7,16,19,24,27,31,34,44,47,     5,8,14,17,21,30,32,37,41,46,
 4,9,14,19,22,29,35,38,46,47,  5,8,13,16,21,26,33,40,41,48,     6,7,15,17,28,30,32,39,42,45,
 6,9,15,20,23,24,37,38,42,45,  7,8,16,19,22,25,34,39,43,46,     1,2,17,18,26,29,31,40,47,0,
 1,4,13,18,27,30,33,38,45,46,  2,3,12,15,22,23,39,40,44,47,     8,9,11,17,24,25,32,37,49,0};
    int TestKey;
    map<int,int> Occurrences;

    for(TestKey = 1; TestKey < 50; ++TestKey)
    {
        Occurrences = CheckOccurrence(TestArray,180,TestKey);
        if( Occurrences[0])
        {
            
            cout << TestKey << " occurs " << Occurrences[0] << endl;
            for(int i = 1; i < Occurrences[0]+1; ++i);
            while(Occurrences[0]>=6) // gdy usunie się petle "while" wyswietlane sa wystapienia  
            { cout <<TestKey << " occurs " << Occurrences[0] << endl;}//wszystkich liczb;
            // z ta petla wyswietla sie tylko wystapienie pierwszej liczby wystepujacej 6 razy 
            //a mianowicie liczby 9, a ponadto warunek ten spełnia jeszcze liczba 40, co zrobić?       
        }
        else
            cout << TestKey << " does not occur in the array"<< endl;
        cout << endl;
    }
    system("PAUSE");
    return 0;   
}

który zlicza ilość wystąpień liczb w tablicy nie interesują mnie wszystkie wartości. Interesuje mnie tylko liczba wystąpień >= 6. Dodałem pętlę "while", która wyswietla tylko liczby wystepujące 6 lub wiecej razy. Teraz program wyłapuje tylko pierwszą z tych liczb tzn. 9, a jest jeszcze liczba 40, ktora też spełnia to kryterium. Co mam zrobić? Może zamiast "while" zastosować "do... while"?</cpp>

0

while Ci sprawdza dopóki warunek jest prawdziwy jeżeli nie to wychodzi ;)

0

To co proponujesz zrobić, żeby wyświetliło te dwie spełniające warunek liczby, albo większą ich ilośc w innych przypadkach, a reszty nie ?

0

wydaje mi się że trochę przekombinowane tam jest.. ja bym po prostu forem po wszystkich elementach tablicy occurences polecial i sprawdzil czy sa wieksze od 6:
f(Occurrences[i]>=6)

0

Już tego próbowałem, ale co najwyżej wyświetlało dwa razy te poszukiwane elementy tuż pod sobą, co już zwracało lepiej uwagę czytającego w tym gąszczu wyników. Może zbyt goraczkowo próbowałem i nie zastanowiłem się jak wywalić resztę wyników.Czyli generalnie jakiś odzew był, a ja może za szybko to skreśliłem. Tak czy inaczej, pora jest późna, więc chyba dziś już dam spokój. Trzymaj się ciepło!
Jutro wejdę na forum ok. 9 wieczór i dam znać co zdziałałem.

0

Zainspirowało mnie to podwójne wyswietlenie poszukiwanych liczb. Pomyślałem trochę i zrobiłem. Kod powinien wyglądać tak:
int TestKey;
map<int,int> Occurrences;

for(TestKey = 1; TestKey < 50; ++TestKey)
{
    Occurrences = CheckOccurrence(TestArray,180,TestKey);
    if( Occurrences[0])
    {
        if(Occurrences[0]>=6)
        {
        cout<<TestKey<< " occurs " << Occurrences[0] << endl;
        }                   

Dzięki wszystkim i dobranoc!

0

ja preferuje taki sposób. Twój jest zdecydowanie przekombinowany:

#include <iostream>
#include <mem.h>
#include <conio.h>

using namespace std;

int main()
{
    int TestArray[] = {
3,10,11,14,22,23,32,35,43,     44,6,9,16,19,24,29,37,38,45,48,  2,5,13,18,25,30,31,40,41,0,
2,5,16,19,25,30,34,39,45,48,   1,9,12,13,21,24,33,36,44,49,     3,8,15,20,23,26,35,40,43,46,
6,9,13,20,28,29,33,40,43,48,   2,7,16,19,24,27,31,34,44,47,     5,8,14,17,21,30,32,37,41,46,
 4,9,14,19,22,29,35,38,46,47,  5,8,13,16,21,26,33,40,41,48,     6,7,15,17,28,30,32,39,42,45,
 6,9,15,20,23,24,37,38,42,45,  7,8,16,19,22,25,34,39,43,46,     1,2,17,18,26,29,31,40,47,0,
 1,4,13,18,27,30,33,38,45,46,  2,3,12,15,22,23,39,40,44,47,     8,9,11,17,24,25,32,37,49,0};

  const int n = sizeof(TestArray) / sizeof(int);
  const int range = 100;
  const int minval = 6;

  int occurences[range];
  memset(occurences,0,range*sizeof(int));
  for (int i=0; i<n; ++i)
    occurences[TestArray[i]]++;

  for (int i=0; i<range; ++i)
    if (occurences[i]>=minval)
      cout << "liczba " << i << " wystapila " << occurences[i] << " razy\n";

  getch();
  return 0;
}
0

mam jedno proste pytanie:
na cholere zakładasz dwa identyczne tematy?
http://4programmers.net/Forum/viewtopic.php?id=149757

0

Twój sposób jest rzeczywiście prostszy. Szacunek!
Dwa identyczne tematy założyłem ponieważ niektórzy zaglądają pod C++, a inni pod Newbie. Jeżeli popatrzysz na posty, to ich ilość zasadniczo się różni od siebie. Ale jeżeli jestem juz przy słowie, to byłbym wdzięczny gdyby ktoś zerknął jeszcze na taki kod:
#include "IndexCombination.h"
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <map>
#include <sstream>
using namespace std;
using namespace stdcomb;

bool GetNextComb(std::vector<unsigned int="int"> &vi);
struct Element
{
char name[6];
int numbers[30];
char chain[90];
};
const Element elements[] = {
{
"ia11",
{3,9,17,21,24,31,33,36,42,49,4,8,19,22,28,30,34,39,43,47,2,6,10,13,14,25,29,37,38,46},
"3,9,17,21,24,31,33,36,42,49,4,8,19,22,28,30,34,39,43,47,2,6,10,13,14,25,29,37,38,46"
}, {
"ia34",
{1,6,12,15,22,27,31,32,41,42,4,7,14,17,23,30,33,36,45,48,2,9,13,18,21,26,34,39,44,49},
"1,6,12,15,22,27,31,32,41,42,4,7,14,17,23,30,33,36,45,48,2,9,13,18,21,26,34,39,44,49"
}, {
"ia72",
{3,8,11,18,22,25,36,37,43,46,1,6,16,17,23,28,35,40,41,44,2,5,12,19,24,27,31,34,42,49},
"3,8,11,18,22,25,36,37,43,46,1,6,16,17,23,28,35,40,41,44,2,5,12,19,24,27,31,34,42,49"
}, {
"ia167",
{3,4,12,15,21,28,32,39,47,48,6,9,16,17,29,30,31,38,41,42,7,8,11,20,26,27,34,35,45,46},
"3,4,12,15,21,28,32,39,47,48,6,9,16,17,29,30,31,38,41,42,7,8,11,20,26,27,34,35,45,46"
}, {
"ia190",
{3,10,11,14,22,23,32,35,43,44,6,9,16,19,24,29,37,38,45,48,2,5,13,18,25,30,31,40,41,0},
"3,10,11,14,22,23,32,35,43,44,6,9,16,19,24,29,37,38,45,48,2,5,13,18,25,30,31,40,41,0"
}, {
"ia21",
{2,5,16,19,25,30,34,39,45,48,1,9,12,13,21,24,33,36,44,49,3,8,15,20,23,26,35,40,43,46},
"2,5,16,19,25,30,34,39,45,48,1,9,12,13,21,24,33,36,44,49,3,8,15,20,23,26,35,40,43,46"
}, {
"ia64",
{6,9,13,20,28,29,33,40,43,48,2,7,16,19,24,27,31,34,44,47,5,8,14,17,21,30,32,37,41,46},
"6,9,13,20,28,29,33,40,43,48,2,7,16,19,24,27,31,34,44,47,5,8,14,17,21,30,32,37,41,46"
}, {
"ia102",
{4,9,14,19,22,29,35,38,46,47,5,8,13,16,21,26,33,40,41,48,6,7,15,17,28,30,32,39,42,45},
"4,9,14,19,22,29,35,38,46,47,5,8,13,16,21,26,33,40,41,48,6,7,15,17,28,30,32,39,42,45"
}, {
"ia178",
{6,9,15,20,23,24,37,38,42,45,7,8,16,19,22,25,34,39,43,46,1,2,17,18,26,29,31,40,47,0},
"6,9,15,20,23,24,37,38,42,45,7,8,16,19,22,25,34,39,43,46,1,2,17,18,26,29,31,40,47,0"
}, {
"ia180",
{1,4,13,18,27,30,33,38,45,46,2,3,12,15,22,23,39,40,44,47,8,9,11,17,24,25,32,37,49,0},
"1,4,13,18,27,30,33,38,45,46,2,3,12,15,22,23,39,40,44,47,8,9,11,17,24,25,32,37,49,0"
}
};

int main(int argc, char *argv[])
{

CIdxComb cb;
cb.SetSizes(10,6);

vector<unsigned int="int"> combination(6);
combination[0] = 0;
combination[1] = 1;
combination[2] = 2;
combination[3] = 3;
combination[4] = 4;
combination[5] = 5;

int Total = 0;

while(cb.GetNextComb(combination))
{
Total++;
cout << "Combination number. " << Total << endl;
for (unsigned i = 0; i < combination.size(); i++)

   {
     const Element &element = elements[combination[i]];
     cout << element.name << ": " << element.chain  << endl;
     
     
  }
  cout << endl;

}
system("PAUSE");
return EXIT_SUCCESS;
}

Kod kompiluje się bez zastrzeżeń, ale niestety wynik jest błędny! Otóż ilość kombinacji elementów po 6 z 10-ciu wynosi ogółem 210, a program liczy jedynie 209. Mam niejasne przeczucie, że chodzi tu o plik nagłówkowy IndexCombination.h, a w szczególności o funkcję GetNextComb. Najwyraźniej program "obcina" jedną kombinację. Próbowałem już kilku sztuczek, ale bez rezultatu. W razie czego mogę też podrzucić headera, ale będę na forum dopiero ok. 21.00. Pozdrawiam wszystkich!

0

na oko jest coś takiego jak GetFirstCombination, które jest albo standardowo przypisane albo je pomijasz. mogę się mylić, ale z reguły jak coś jest następne to i coś jest pierwsze

0

Nie wiem czy GetFirstCombination da się skleić z GetNextCombination. Jakoś nie mogę sobie tego wyobrazić. Obawiam się, że w takim przypadku skończy się tylko na tej pierwszej kombinacji, albo w ogóle kompilator krzyknie, że nie zna takiej funkcji, ale pewności to nie mam. Muszę przemyśleć sprawę. W header file nie ma GetFirstCombination. Służę plikiem nagłówkowym, też trochę skomplikowany:
#include "IndexCombination.h"

using namespace stdcomb;

void CIdxComb::Init( unsigned int SetSize, unsigned int CombSize )
{
// Assign CombSize
////////////////////////
if( CombSize == 0 )
CombSize = 1;

m_ArrSize = CombSize;
m_LastIdx = CombSize - 1;

// Assign SetSize
////////////////////////
if( SetSize == 0 )
	SetSize = 2;

if( CombSize > SetSize )
	CombSize = SetSize;

m_SetSize = SetSize;
m_LastSetIdx = SetSize - 1;

}

bool CIdxComb::SetSizes( unsigned int SetSize, unsigned int CombSize )
{
if( SetSize == 0 )
return false;

if( CombSize == 0 )
	return false;

if( CombSize > SetSize )
	return false;

m_ArrSize = CombSize;
m_LastIdx = CombSize - 1;

m_SetSize = SetSize;
m_LastSetIdx = SetSize - 1;

return true;

}

bool CIdxComb::GetNextComb( std::vector<unsigned int="int"> &vi )
{

// Check if the last element is at the end
if( vi[m_LastIdx] == m_LastSetIdx )
{
	if( m_ArrSize == 1 ) // Completed
		return false;

	// Check if the subsequent elements(counted from back)
	// is also at their subsequent positions
	//////////////////////////////////////////////////////
	bool Completed = true;
	// Incomplete Index, init value not used
	unsigned int IncompIdx = m_LastIdx - 1; 
	
	bool FirstIdx = false;
	unsigned int ArrIdx = m_LastIdx - 1;

	unsigned int SetIdx = m_LastSetIdx - 1;
	
	while( !FirstIdx )
	{
		if( vi[ArrIdx] != SetIdx )
		{
			Completed = false;
			IncompIdx = vi[ArrIdx] + 1;
			break;
		}

		if( SetIdx )
			--SetIdx;
	
		if( !ArrIdx )
			FirstIdx = true;
		else
			--ArrIdx; 
			 
	}

	if( Completed )
		return false;
	else
	{
		for( unsigned int i=ArrIdx; i<=m_LastIdx; ++i, ++IncompIdx )
		{
			vi[i] = IncompIdx;
		}
	}

}
else if ( vi[m_LastIdx] < m_LastSetIdx )
{
	(vi[m_LastIdx])++;
}
else // bigger than the m_LastIdx! Impossible!
{
	return false;
} 

return true;

}

Trochę długi, ale interesujący i nie ma w nim takiej funkcji.

0

chwilka. a próbowałeś zamiast pętli while {...} zrobić do {...} while?

0

I znów miałeś rację. Pętla do...while załatwiła sprawę. Oto co zrobiłem:
do {
Total++;
cout << "Combination number. " << Total << endl;
for (unsigned i = 0; i < combination.size(); i++)
{

             const Element &element = elements[combination[i]];
             cout << element.name << ": " << element.chain << endl;
             
             }
      }
   while(cb.GetNextComb(combination));

Jeżeli można to jeszcze jakoś uprościć, to proszę o uwagi. Ale chyba już się bardziej nie da.

Jednak teraz bardziej mnie zainteresowała następująca kwestia. Czy można jakoś te dwa programy ze sobą "pożenić". Chodziłoby o to, aby program liczył te 210 kombinacji gdzieś w tle, a następnie obliczał
ilość wystąpień elementów w każdej z nich i podawał tylko te elementy, które występują sześć lub więcej razy. Innymi słowy OUTPUT powinien wyglądać jakoś tak:
Combination number 1

Liczba 3 wystąpiła 6 razy
Liczba 48 wystąpiła 7 razy
Liczba 0 wystąpiła 8 razy

Combination number 2
Liczba 5 wystapiła 6 razy
itd.

Jeszcze nie próbowałem tego robić, ale wszelkie uwagi i sugestie są mile widziane. Nie robię z tego programu żadnej tajemnicy. Każdy może sobie go wykorzystać do własnych celów. Najbardziej cieszy mnie to, że dyskusja nasza jest śledzona przez forumowiczów, którzy przy okazji też mogą się czegoś nauczyć. Wbrew pozorom, problem wcale nie jest taki banalny na jaki wygląda, a przy okazji po raz kolejny okazało się, że polscy programiści są po prostu lepsi. Muszę w tym miejscu dodać, że na anglojęzycznych portalach programistycznych jest wprawdzie dużo materiałów do wykorzystania, ale
ludziska na forum z tym problemem sobie nie poradzili.
Trochę się rozpisałem, a muszę lecieć do pracy. Pozdrawiam wszystkich! Do wieczora.

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