I need to find a number in the 2D array.
Columns are sorted (from smallest value to the biggest).
Here is my code:
const int SIZE = 4;
const int NOT_FOUND = 1;
int binarySearch(int mat[][SIZE], int &line , int num);
void main()
{
int num, index, mat[SIZE][SIZE] = { 11,1,5,11,
11,6,7,2,
8,7,7,7,
0,12,9,10 };
int line = sizeof(mat) / sizeof(mat[0][0]);
cout << "please type a number to search: " << endl;
cin >> num;
index = binarySearch(mat, line, num);
if (index == NOT_FOUND) {
cout << "The value: " << num << "doesn't exist in the array\n";
}
else {
cout << "The value: " << num << " exists in line " << line+1
<<" and column: " << index+1 << endl;
}
system("pause");
}
int binarySearch(int mat[][SIZE], int &line, int num)
{
for (int j = 0; j < SIZE; j++)
{
int low = 0;
int high = SIZE - 1;
int middle;
while (low <= high)
{
middle = (low + high) / 2;
if (num == mat[middle][j])
{
line = middle;
return j;
}
else if (num < mat[middle][j]) {
high = middle - 1;
{
else {
low = middle + 1;
}
}
}
return NOT_FOUND;
}
The program doesn't find all the numbers in the array.
Something doesn't work.
What is the problem?
Your binarySearch doesn't go through all the numbers, it checks the first number, so in your case 11, then it moves to the next number, but it skips the whole row of numbers (1, 5, 11) and the first number in second row and then moves to the next second number which will be 6 in second row.
Since you have a Matrix of number it consists of Rows and Columns, that means you have to create two loops for(...), once for the Rows and one for the Columns so you can go through all the numbers in your 2D array.
I recommend setting a Break point on the binarySearch function and going through with that, it'll help you a lot.
A few things that I see wrong in your code are ::
1) It appears that you are applying binary search to every column in your input array, and if the number is not found in the corresponding column, you increment j and move to the next column.
The most important thing about binary search is "The array in which you are searching should always be sorted". Since here you are searching columns, all your columns shall be sorted! Which appears unsorted in the code above! Which is a major reason why you don't find most elements. So, your input array shall look something like this (if you want to apply binary search) ::
int mat[SIZE][SIZE] = { 0,1,5,2,
8,6,7,7,
11,7,7,10,
11,12,9,11 }
All columns sorted in ascending order here!
2) The value of the variable NOT_FOUND you have set it to 1 and from your function you return the column number from where you found the element. So, if you found the element in the 2D array in column 1 your program will print Element Not Found because the condition if (index == NOT_FOUND) evaluates to true if the element was found in column 1. So, a better solution would be to change the value of NOT_FOUND to some negative value, since it can never be the column number in a valid case. Something like this ::
const int NOT_FOUND = -1;
Ideone link of code :: http://ideone.com/9cwHnY
Related
binary search is sorta working if it finds the value it will correctly return the pos at which the value was found at in array the issue is its only looping through first half of array its never hitting the else statement to increase the start index and always hits the if statement regardless of if the searchingFor word is before or after alphabetically. the players array list has been sorted alphabetically. Any help would be amazing :)
cout << "type name youd like to search for" << endl;
char playerChoice[10] = "len";
databaseFunctions.SelectionSort(databaseFunctions.players, databaseFunctions.size);
int result = databaseFunctions.BinarySearch(databaseFunctions.players, 0, databaseFunctions.size, playerChoice);
int DataBaseFunctions::BinarySearch(Player* players, int start_index, int end_index, char searchingFor[])
{
while (start_index <= end_index)
{
int middlePoint = (start_index + end_index) / 2;
if (strcmp(players[middlePoint].playerName, searchingFor) == 0)
return middlePoint;
if (searchingFor < players[middlePoint].playerName)
end_index = middlePoint - 1;
else
start_index = middlePoint + 1; // need to fix thiss never hitting else regardless always just -1 instead of adding 1
}
return -1;
}
I am trying to search an array using a binary search algorithm when the array is in ascending order. I don't know why every single time I search for a value it says it isn't in the array... Here is my code.
int main()
{
int found, value;
int array[] = {0,2,2,3,5,9,11,12,12,12,13,17,18,19,19,34}; // array to be searched
cout << "Enter an integer to search for:" << endl;
cin >> value;
found = binarySearch(array, SIZE, value); //function call to perform the binary search
//on array looking for an occurrence of value
if (found == -1)
cout << "The value " << value << " is not in the list" << endl;
else
{
cout << "The value " << value << " is in position number "
<< found + 1 << " of the list" << endl;
}
system("pause");
return 0;
}
//**********BINARY SEARCH**********
int binarySearch(int array[],int numElems,int value) //function heading
{
int first = 0; // First element of list
int last = numElems - 1; // last element of the list
int middle; // variable containing the current
// middle value of the list
while (first <= last)
{
middle = first + (last - first) / 2;
if (array[middle] == value)
return middle; // if value is in the middle, we are done
else if (array[middle] < value)
last = middle - 1; // toss out the second remaining half of
// the array and search the first
else
first = middle + 1; // toss out the first remaining half of
// the array and search the second
}
return -1; // indicates that value is not in the array
}
your condition for binary search is inverted.
if array[middle] < value then you want to search for your element in upper half and not the lower half.
Exchange last = middle - 1 and first = middle + 1, and binary search would work fine.
Lets search for 7.
2 3 5 6 [7] 8 8 9
0 1 2 3 4 5 6 7
^f....^m............^l
m = (7 + 0) / 2 = 3
Element with index 3 is 6.
6 < 7. Then we should change first to mid + 1.
If mid value is less than value for search, then we should change first, so that value for search is still in interval [first; last]
I have to write a function that accepts an array of integers as arguments
and display back to the user the "unusual" digits. Digits that appear only
in one integer and not the rest, and then sort the array so that the integer
with the largest occurrences of unusual digits is to be moved to the first
element of the array, then followed by the integer with the next
largest number of occurrences of unsual digits.
Input:
113
122
1000
Output:
There is 3 unusual digits:
0 occurs 3 times in 1000
2 occurs 2 times in 122
3 occurs 1 time in 113
Sorted:
1000
122
113
My question is how can I retrieve the integers that were associated with the unusual digits so that I can sort them in the future?
I would like to know which integer digit 0 came from and how many times it occurred in that integer.
Here's what I have so far, I apologize if the code is bad. I am not allowed to use any additional libraries other than iostream and all function calls must be written myself.
#include <iostream>
using namespace std;
void getUncommon(int* iAry, int size) {
const int size2 = 10;
int* tmpAry = new int[size];
int totalCount[size2] = { 0 };
int currentCount[size2] = { 0 };
int totalUncommon = 0;
int i, j;
for (i = 0; i < size; i++) {
tmpAry[i] = iAry[i];
if (tmpAry[i] < 0)
tmpAry[i] *= -1;
for (j = 0; j < size2; j++)
currentCount[j] = 0;
if (tmpAry[i] == 0) {
currentCount[0] = 1;
}
while (tmpAry[i] / 10 != 0 || tmpAry[i] % 10 != 0){
currentCount[tmpAry[i] % 10] = 1;
tmpAry[i] /= 10;
}
for (j = 0; j < size2; j++) {
totalCount[j] += currentCount[j];
}
}
for (i = 0; i < size2; i++) {
if (totalCount[i] == 1) {
totalUncommon++;
}
}
cout << "Total of uncommon digits: " << totalUncommon << endl
<< "Uncommon digits:\n";
if (totalUncommon == 0) {
cout << "\nNo uncommon digits found.";
}
else {
for (i = 0; i < size2; i++) {
if (totalCount[i] == 1) {
cout << i << endl;
}
}
}
return;
}
int main(){
int* my_arry;
int size;
int i;
cout << "How many integers? ";
cin >> size;
my_arry = new int[size];
for (i = 0; i < size; i++) {
cout << "Enter value #" << i + 1 << " : ";
cin >> my_arry[i];
}
cout << "\nThe original array:" << endl;
for (i = 0; i < size; i++) {
cout << my_arry[i] << endl;
}
cout << "\nCalling function -\n" << endl;
getUncommon(my_arry, size);
delete[] my_arry;
return 0;
}
Thanks ahead of time.
You can create a map with the digits 0 1 2 ... 9 as the key, and a pair of pointer to/index of integer containing the digit and number of occurrences of the digit in the integer as the value of the key-value pair.
Start iterating on the integer list, extracting the digits and their number of occurrences from each integer. You can do that by either using the modulo operator, or using string functions (after converting the integer to string).
Now, for each integer, access the map of digits for all the digits in the integer, and if the value is uninitialised, update the value with the pointer/index to this integer and the number of occurrences of the digit in this integer. If the map entry is already populated, that means that it's not an "unusual" digit. So you can mark that map entry with a marker that conveys that this particular digit is not "unusual" and hence no need to update this entry.
After iterating over the entire integer list in this manner, you can iterate the map to find out which digits are unusual. You can also access the containing integer from the pointer/index in the value portion of the map's key-value pair. You can sort these entries easily using any sorting algorithm (since the number of values to be sorted is very small, no need to worry about time complexity, pick the easiest one) on the number of occurrences value.
The code below keeps getting me a "Debug Assertion Failed!" error. I think I've isolated it to:questions.erase(questions.begin() + number);
The goal of the code is to randomly ask one of the questions from the test bank vector "questions". I haven't entered all the questions yet because I was trying to figure out the mechanics before hand.
Thanks in advance for your help!
int nomen()
{
int number;
string ans = "No Answer";
cout << "\nIn the Nomenclature Game you will be asked to name chemical compounds or give their UPAC symbols." << endl;
vector<string> questions;
vector<string> answers;
questions.push_back("MgO");
answers.push_back("magnesium oxide");
srand((unsigned)time(0));
number = (rand () % questions.size()) + 1;
for (int i = 0; i < questions.size(); ++i)
{
cout << questions[number] << endl;
questions.erase(questions.begin() + number);
}
return 0;
}
questions.erase(questions.begin() + number); is off the end of the array.
questions.begin() is equivalent to position 0 and
number is equal to questions.size()
So 0 + size = size which is 1 past the end of the vector.
This expression
number = (rand () % questions.size()) + 1;
yields either 1 (when rand() returns any value except 0) or 2 (when rand() returns 0).
Your vectors have sizes equal to 1.
Thus in this statement
questions.erase(questions.begin() + number);
iterator questions.begin() + number is invalid if number is equal to 2. If number is equal to 1 then questions.begin() + number is equivalent
to questions.end()
Also in the loop
for (int i = 0; i < questions.size(); ++i)
{
cout << questions[number] << endl;
questions.erase(questions.begin() + number);
}
you are trying to erase the same element that can be already erased in the preceeding iteration.
The Programming-Challenges website marked it as a wrong answer. I checked with sample inputs and they were all correct. I added an optimization to the code, I made it so it doesn't check numbers that are known to be in another number's sequence, since it would be a subsequence and obviously have a shorter cycle length.
Also I just got back into programming so the program isn't too terse but I hope it is readable.
Here is the code:
#include <iostream>
#inclue <vector>
struct record
{
int number;
int cyclelength;
};
void GetOutput(int BEGIN, int END)
{
//determines the output order at the end of function
bool reversed = false;
if (BEGIN > END)
{
reversed = true;
int temp = BEGIN;
BEGIN = END;
END = temp;
}
vector<record> records;
for (int i = BEGIN; i <= END; ++i)
{
//record to be added to records
record r;
r.number = i;
r.cyclelength = 1;
records.push_back(r);
}
int maxCycleLength = 1;
//Determine cycle length of each number, and get the maximum cycle length
for (int i =0;i != records.size(); ++i)
{
//
record curRecord = records[i];
//ABCD: If a number is in another number's sequence, it has a lower cycle length and do not need to be calculated,
//set its cyclelength to 0 to mark that it can be skipped
if (curRecord.cyclelength != 0)
{
//
while (curRecord.number != 1)
{
//next number in the sequence
int nextNumber;
//finds the next number
if (curRecord.number % 2 == 0)
nextNumber = curRecord.number / 2;
else
{
nextNumber = curRecord.number * 3 + 1;
//if nextNumber is within bounds of input, mark that number as skippable; see ABCD
if (nextNumber <= END)
{
records[nextNumber - BEGIN].cyclelength = 0;
}
}
curRecord.number = nextNumber;
curRecord.cyclelength += 1;
}
maxCycleLength = max(curRecord.cyclelength, maxCycleLength);
}
}
if (reversed)
{
cout << END << " " << BEGIN << " " << maxCycleLength;
}
else
{
cout << BEGIN << " " << END << " " << maxCycleLength;
}
}
int main(){
//The first and last numbers
vector< vector<int> > input;
int begin, end;
while (cin >> begin >> end)
{
//storage for line of input
vector<int> i;
i.push_back(begin);
i.push_back(end);
input.push_back(i);
}
for (int i = 0;i != input.size(); ++i)
{
GetOutput(input[i][0], input[i][1]);
cout << endl;
}
return 0;
}
I'll try to give you a hint to nudge you into figuring out the problem.
The sample inputs are good as a smoke test, but they're often not good indicators that your program can handle the more extreme test cases too. You should always test with more than the sample inputs. If my calculations are correct, your program will produce the wrong result for the following input:
999000 999250
For reference, the expected output for this is:
999000 999250 321
There, I narrowed your search space down to 251 cycles :) Now get your debugger and finish the job.
Anyway, what follows is the full explanation and solution in spoiler markup. Mouse over the blank space if you want to read it, stay put if you want to figure it yourself.
The problem states that i and j are less than one million and that no operation overflows a 32-bit integer. This means that no intermediate result will be larger than 4294967295. However, an int is a signed type, so, even if it has 32-bits, it only has 31 bits for the absolute value, and thus cannot fit any number larger than 2147483647. Numbers larger than these occur in the cycles of for several Ns in the problem range, one of which is 999167. Using an unsigned 32 bit integer is one solution.
There is nothing mystery. The largest intermediate number overflows 31-bit of the signed integer. You need to declare record.number and nextNumber as unsigned int.