Checking for validity in 2d array - c++

so i am creating a sudoku validity checker program in C++. the program takes in a csv file with an already completed sudoku board. the program is supposed to read the file line by line and put the numbers into a 2d array (which it's doing just fine). i'm getting stuck on the checking whether or not there are any duplicate numbers in a row (i assume that if i can get this working then the columns should be fairly similar). i know how the algorithm is supposed to work in my head but i just can't seem to get it into code.
Algorithm:
1) look at each row and check for numbers 1 through 9 making sure that they only appear once (if at all)
2) if a duplicate is found (which means that some number is missing) tell the user at what row and column the error was found.
3) otherwise move on to the next row and do it again
i think that it's supposed to be a for loop running this but it's been a long time since i've coded in C++ and nothing on the internet has been very helpful to me.
Any help is appreciated.
Here is my code so far:
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <thread>
using namespace std;
int *board[9];
int row, col;
void printBoard();
void is_row_ok();
int main()
{
for (int i = 0; i < 9; ++i)
{
board[i] = new int[9];
}
printBoard();
is_row_ok();
cout << endl;
return 0;
}
void printBoard()
{
string line;
string val;
ifstream myFile("Testfile1.txt");
for (int row = 0; row < 9; ++row)
{
string line;
getline(myFile, line);
if (!myFile.good())
break;
stringstream iss(line);
cout << endl;
for (int col = 0; col < 9; ++col)
{
string val;
getline(iss, val, ',');
if (!iss.good())
break;
stringstream convertor(val);
convertor >> board[row][col];
cout << board[row][col] << " ";
}
}
cout << endl;
cout << endl;
}
void is_row_ok()
{
bool found = false;
int i, j;
for (int i = 0; i < 10; ++i) //<------ edit starts here
{
int counter = 0;
for (int j = 0; j < 9; ++j)
{
if(board[row][j] == i)
{
cout << "Before " << counter << endl;
counter++;
cout << counter << endl;
}
if(counter > 1)
break;
}
}
}

The easiest way I can think of is 2 loops (one inside of another): 1 gets you through numbers 1 to 9 and the other goes through the elements of the row. Small tip with code.
for(int i=1;i<10;i++){
int counter =0;
for(int j=0;j<9;j++){
if(board[row][j] ==i)counter ++;
}
if(counter >1) break; //here you check that there´s only one number on the row.
}
Of course, there are other ways to do it, this one is quite basic and slow.
-------------------------------------EDIT-------------------------------------------
Your function should be bool in order to know if there´s repeated number or not.
bool is_row_ok(vector<vector<int> board)//I suggest you use vectors instead of arrays.
{
//i and j are declared on for, there´s no need to declare them again.
for (int i = 0; i < 10; ++i)
{
int counter = 0;
for (int j = 0; j < 9; ++j)
{
if(board[row][j] == i)counter++;
if(counter > 1)return false;
}
}
return true;
}
Now you call this function on main. If function returns true, everything is ok, if it returns false, you have a repeated number.
int main(){
if(is_row_ok(board)cout<<"No number repeated"<<endl;
else cout << "Number repeated"<<endl;
return 0;
}

I think the easiest way is to use std::sort + std::unique as unique returns iterator to the new end of range.
#include <algorithm>
using namespace std;
int main()
{
int n[15] = { 1, 5, 4, 3, 6, 7, 5, 5, 5, 4, 2, 3, 9, 8, 9 };
int* end = n + 15;
sort(n, n + 15);
bool has_no_duplicates = (unique(n, n + 15) == end);
return 0;
}
This is just an example but you should get the idea.

Related

Why is my loop not returning the right answer?

I can't figure it out. What is wrong with my code? I am new to programming.
Program required output: Write a C++ program to find the maximum-occurring character in an array, using a loop.
My code:
#include <string.h>
using namespace std;
void FindMaxChar(char Word[])
{
int count = 0;
int max = 0;
char index = 0;
int length = strlen(Word);
for (int i = 0; i < length; i++)
{
index = Word[i];
for (int j = 0; j < length; j++)
{
if (index == Word[j])
{
count++;
}
}
if (count > max)
{
max = count;
index = Word[i];
}
}
cout << index << " is repeating " << max << " times.";
}
int main()
{
char Word[100] = {0};
cout << "Enter the Word = ";
cin.get(Word,100);
FindMaxChar(Word);
}
My Output:
Enter the Word = caaar
r is repeating 11 times.
You never reset count each loop. So you continue incrementing it but never clear it.
Add count = 0 to the beginning of the outer for loop:
for (int i = 0; i < length; i++)
{
count = 0; // Reset counter
You're also trying to use index for two different purposes. You're both using it to store the current character you're looking at (not an index, kind of confusing that you named it like that), AND the character you've seen the most (still not an index, also confusing).
Instead, you need another variable here.
Also note that if you declare Word as char Word[100], it can only hold a c-string of length 99 (to leave room for the null character). So your cin should actually be:
cin.get(Word, 99);
Thanks to the great people of this community.
I am able to find my error and corrected it.
Correct Code :
#include <iostream>
#include <string.h>
using namespace std;
void FindMaxChar(char Word[])
{
int count = 0;
int max = 0;
char index = 0;
char final = 0;
int length = strlen(Word);
for (int i = 0; i < length; i++)
{
index = Word[i];
count = 0;
for (int j = 0; j < length; j++)
{
if (index == Word[j])
{
count++;
}
}
if (count > max)
{
max = count;
final = index;
}
}
cout << final << " is repeating " << max << " times.";
}
int main()
{
char Word[100] = {0};
cout << "Enter the Word = ";
cin.get(Word,99);
FindMaxChar(Word);
}

Checking Duplicates Numbers In Array c++

I wrote a simple C++ program that finds how many duplicates are in the array.
This works perfectly for me but this is very long code. And I would like to know if there is any short code which may perform this task successfully:
#include<iostream>
using namespace std;
int main()
{
int a[10];
int reper=0,word=0,flage=0,number[10]={
0
};
//Getting Input From User
for (int i = 0; i <=9; i++)
{
cout<<"Enter The Value For "<<i<<" Index"<<endl;
cin>>a[i];
}
//Checking The Duplicates Numbers
for (int i = 0; i <= 9; i++)
{
reper=0;
flage=0;
for (int j = 0; j <=9; j++)
{
if (a[i]==a[j])
{
if (i!=j)
{
reper++;
}
}
}
number[i]=a[i];
for (int k = 0; k <=9; k++)
{
if (i!=k)
{
if(number[i]==number[k])
{
flage=1;
break;
}
}
}
//If There Are Duplicates Then Prints That Numebr, How Many Times It Repeated And Total Occurance Of That Number In The Array
if (reper!=0&&flage==0)
{
cout<<"Repeated Number Of The Array Is : "<<a[i]<<" ";
cout<<"And This Number Repeated "<<reper<<" Times "<<"And Total Occurance Of This Number is : "<<reper+1<<endl;
word=a[i];
}
}
//If There Is Nothing Any Duplicate In The Array Then Simply Prints This Message On Console
if (reper==0&&word==0)
{
cout<<"There Is Nothing Any Repeated Number Of This Array: "<<endl;
}
system("Pause");
return 0;
}
IMHO the easiest way to implement this - using http://en.cppreference.com/w/cpp/container/multiset. It has logarithmic complexity and inner methods to count repeated items.
Refer an example below:
#include <iostream>
#include <set>
int main(int argc, char *argv[])
{
std::multiset<int> ms;
//Getting Input From User
for (int i = 0; i <=9; i++)
{
std::cout<<"Enter The Value For "<<i<<" Index"<<std::endl;
int val;
std::cin>>val;
ms.insert(val);
}
bool repeated_number_found=false;
std::multiset<int>::const_iterator it = ms.begin();
while (it != ms.end()) {
int reper=ms.count(*it);
if (reper > 1){
std::cout << "Number " << *it << " repeated for " << reper << " times" << std::endl;
repeated_number_found=true;
}
it = ms.upper_bound(*it);
}
if (!repeated_number_found){
std::cout<<"There Is Nothing Any Repeated Number Of This Array"<<std::endl;
}
return 0;
}
But using this container you will loose first entrance of repeated number, if it matters to you, I will recommend using struct or std::pair to hold entrance number with entered number. In this case you will need to provide custom comparator also (refer to doc.)
I think the better way to achieve this would be to sort the array and do something like this :-
(include the header file algorithm before doing this.)
vector <int> a (10,0);
for (int i = 0; i <=9; i++)
{
cout<<"Enter The Value For "<<i<<" Index"<<endl;
cin>>a[i];
}
int count = 0;
sort(a.begin(), a.end());
for(int i = 0; i < a.size() - 1; i++) {
if (a[i] == a[i + 1]) {
count++;
}
}
cout << count << endl;

display wheter or not an array entered by the user is unique or not

I am new to C++ I am making an array based off of user input and displaying whether the array is unique or not. my initial thought is I have to end up creating another array to store values and then compare the elements. My code compiles without errors but does not do what I want it to do. I can't used advanced methods such as hashmaps or vectors. Any help or insight is greatly appreciated!
#include <iostream>
#include <string>
using namespace std;
int main()
{
int myArray[6];
string name;
int i, k;
int ov = 0;
int newVal = 0;
for (int index = 0; index < 6; index++)
{
cout << "Enter number a number: ";
cin >> myArray[index];
}//end loop for
for (i = 0; i < 6; i++)
{
ov = myArray[i];
}
for (k = i + 1; k < 6; k++)
{
if (ov == myArray[k])
{
newVal = 1;
}
}
if (newVal == 1)
{
cout << "Not all unique";
}
else
{
cout << "All unique";
}
cin.get();
return 0;
}

Max Sum Of Integers

EDIT: solved! I was treating negative numbers test case as 0, instead of having the output be negative as well. thanks for the help!
Here is the challenge description: https://www.codeeval.com/open_challenges/17/
I keep getting a partially solved score. I want to know why. As in my eyes, this code works. And I believe that it is O(N) time. Thanks for looking!
Here is my code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
int max(int a, int b)
{
if (a > b)
return a;
else return b;
}
int maxSubArray(vector<int> values)
{
int max_so_far = values[0];
int curr_max = values[0];
for(int i = 1; i < values.size(); ++i)
{
curr_max = max(values[i], curr_max + values[i]);
max_so_far = max(max_so_far, curr_max);
}
return max_so_far;
}
int main(int argc, char *argv[])
{
std::vector<vector<int> > Values; //to hold the values of the stock price change
ifstream file(argv[1]);
std::string line; //for the txt file input
int value = 0; //for holding the value of stock change
while (std::getline(file, line))
{
int pos = 0;
if(line.length() == 0)
continue;
else
{
std::istringstream iss(line);
std::vector<int> list; // temporary list of values to be pushed back into the 2-d vector
while (iss >> value)
{
list.push_back(value);
}
Values.push_back(list);
}
}
for(int i = 0; i < Values.size(); ++i)
{
cout << maxSubArray(Values[i]);
cout << endl;
}
/*
cout << " Printing the values : " << endl;
for (int j = 0; j < Values.size(); ++j)
{
for (int k = 0; k < Values[j].size(); ++k)
cout << Values[j][k] << " ";
cout << endl;
}
*/
return 0;
}
so I swapped out some code now. I get better score but I it's still a partial.
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>
using namespace std;
int max(int a, int b)
{
if (a > b)
return a;
else return b;
}
int maxSubArray(vector<int> values)
{
int max_so_far = values[0];
int curr_max = values[0];
if (curr_max < 0)
{
curr_max = 0;
max_so_far = 0;
}
for(int i = 1; i < values.size(); ++i)
{
curr_max = max(values[i], curr_max + values[i]);
curr_max = max(curr_max, 0);
max_so_far = max(max_so_far, curr_max);
}
return max_so_far;
}
int main(int argc, char *argv[])
{
std::vector<vector<int> > Values; //to hold the values of the stock price change
ifstream file(argv[1]);
std::string line; //for the txt file input
std::string token; //for the subtring that will be converted from char to int
int value = 0; //for holding the value of stock change
int count = 0;// for holding how many total cases
while (!file.eof())
{
int pos = 0;
getline(file, line);
if(line.length() == 0)
continue;
else
{
std::vector<int> list; // temporary list of values to be pushed back into the 2-d vector
while ((pos = line.find(",")) != std::string::npos )
{
token = line.substr(0,pos);
value = atoi(token.c_str());
line.erase(0, pos + 1);
list.push_back(value);
}
value = atoi(line.c_str());
list.push_back(value);
Values.push_back(list);
++count;
}
}
for(int i = 0; i < Values.size(); ++i)
{
cout << maxSubArray(Values[i]);
cout << endl;
}
cout << " Printing the values : " << endl;
for (int j = 0; j < Values.size(); ++j)
{
for (int k = 0; k < Values[j].size(); ++k)
cout << Values[j][k] << " ";
cout << endl;
}
return 0;
}
Why are you passing the vector by value here?
int maxSubArray(vector<int> values)
That looks like a significant optimization opportunity.
I think you don't read the problem exactly right. When they say 'all contiguous sub ararys', they mean you have to take the max over all i andj of for(idx = i; i < j; ++i) { total += vec[idx]; }. Right now your code basically assumes i = 0 which isn't what you are supposed to do.
Just from looking at the output examples they provide, I can see that your code isn't going to give the answer that they expect.
it seems right, the only thing I can think of is that when the list gets long, your result can overflow, so change int to long long.
Besides technical optimizations suggested in other answers, concerning the algorithm, i think a little fix can make your algorithm work. When curr_max drops to a negative value, due to encountering a negative integer that exceeds curr_max, you can simply drop all the previous integers including the current value and start over. This fix is simple, you can add one line to your loop like this:
for(int i = 1; i < values.size(); ++i)
{
curr_max = max(values[i], curr_max + values[i]);
curr_max = max(curr_max, 0); // <---------------- add this line
max_so_far = max(max_so_far, curr_max);
}

copy one array to another without duplicates C++

The problem is that, I have an array of 10 integers, having some duplicates. The task is to copy this array to another array of same size, but without duplicate values. That is, read one element from array1, compare it with all the elements in array2, if it's already in array2, just skip it or print that it's already in array2, go to second element of array1, and repeat the process.
Now, I've tried this but don't know where's the problem:
#include <iostream>
using namespace std;
int main()
{
int temp;
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
break;
}
}
array2[i] = array1[i-1];
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl;
system("pause");
}
array1 has 10 elements and array2 has 11, so right away the requirements haven't been met. Presumably, having 11 elements was a workaround for using incorrect index values in the for loops; the index should run from 0 to 9, not from 1 to 10.
When you add an element to the second array, you should only check it value against the elements that have already been added, not against the values in the entire array.
Finally, there's an underspecification. Once you've eliminated duplicates, you have fewer than 10 elements; array2 has 10 elements; what values should the extra elements have?
std::unique_copy is your friend:
http://en.cppreference.com/w/cpp/algorithm/unique_copy
remember to sort the source array first
In C++, break immediately ends one loop structure, and starts execution immediately after it. Thus, the line array2[i] = array1[i-1]; executes redardless of whether the inner for loop finds a duplicate. One solution is to set a variable indicating that the value is a duplicate:
int main() {
int temp;
bool isDuplicate; //added this line
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
isDuplicate=false;//added this line
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
isDuplicate=true; //added this line
break;
}
}
if(!isDuplicate) //added this line
array2[i] = array1[i-1];
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl; system("pause"); }
Alternatively (though many programmers would disagree with this practice) you could use a goto statement instead of a break statement:
int main()
{
int temp;
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[11] = {0};
for(int i = 1; i <= 10; i++)
{
temp = array1[i-1];
for(int j = 1; j <= 10; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
i++;
goto duplicate; //added this line
}
}
array2[i] = array1[i-1];
//added next line
duplicate:
}
for(int k = 1; k <= 10; k++)
cout << array2[k] << " " << endl;
system("pause");
}
You could use a std::set to ensure uniqueness for you.
http://en.cppreference.com/w/cpp/container/set
You have three approaches:
compare each element one by one (O(N^2) performance)
sort your reference array and use a binary search to determine if the element exists (O(N*lnN) performance)
create a lookup hash (O(1) performance)
I can see two main sources of problems in your code: 1) the break statement, as it is, does not solve the problem of differentiating between the case when duplicate is found, and when the element in array1 should be added to array2. 2) There is no counter which would store the number of elements inserted so far into array2, this way they could not be copied to array2 next to each other. The code which fixes both is:
#include <iostream>
using namespace std;
int main()
{
int array1[] = {10,2,5,4,10,5,6,9,8,10};
int array2[10];
int array2_elements_inserted = 0;
for(int i = 0; i < 10; i++)
{
int temp = array1[i];
bool isDuplicate = false;
for(int j = 0; j < array2_elements_inserted; j++)
{
if(temp == array2[j])
{
cout << "Duplicate " << temp << endl;
isDuplicate = true;
break;
}
}
if (!isDuplicate)
{
array2[array2_elements_inserted] = temp;
++array2_elements_inserted;
}
}
for(int k = 0; k < array2_elements_inserted; k++)
cout << array2[k] << " " << endl;
// system("pause");
}
Output:
10
2
5
4
6
9
8
First of all, use dynamic containers. Especially have a look at those provide by
the standard library, e.g. std::vector. Second, you should use a set data structure
to keep track of the elements you have seen before, e.g., std::set.
Then it's just an iteration on the input array and appending new elements to the
output array.
Here's an example:
#include <vector>
#include <set>
#include <iostream>
int main() {
// define and print input data
std::vector<int> v1 = {10,2,5,4,10,5,6,9,8,10};
for (int i : v1)
std::cout << i << " ";
std::cout << "\n";
// this will soon contain the output data
std::vector<int> v2;
// a set to keep track of the already seen elements
std::set<int> set;
// iterate the input array using range-based for loop
for (int i : v1) {
// check for duplicates
if (set.find(i) == set.end()) {
// first occurrence, insert to set, append to output data
set.insert(i);
v2.push_back(i);
}
else {
// seen before, do nothing
}
}
// print output data
for (int i : v2)
std::cout << i << " ";
std::cout << "\n";
}
The output:
$ g++ test.cc -std=c++11 && ./a.out
10 2 5 4 10 5 6 9 8 10
10 2 5 4 6 9 8
For reference:
http://en.cppreference.com/w/cpp/container/vector
http://en.cppreference.com/w/cpp/language/range-for
http://en.cppreference.com/w/cpp/container/set
http://en.cppreference.com/w/cpp/container/set/find