Related
I'm trying to find all possible solutions to the 3X3 magic square.
There should be exactly 8 solutions.
My code gets them all but there are a lot of repeats. I'm having a hard time tracking the recursive steps to see why I'm getting all the repeats.
// This program finds all solutions to the magic square for a 3X3
// square where each column, row and diagonal sum is equal
#include <iostream>
using namespace std;
#define SQUARE_SIZE 9
int anyLine = 0;
int currLine = 0;
int numSolutions = 0;
// swap two values in the square.
void swap(int arr[], int idxa, int idxb)
{
int tmp = arr[idxa];
arr[idxa] = arr[idxb];
arr[idxb] = tmp;
}
void printArray(int arr[])
{
for (int i = 0; i < SQUARE_SIZE; i++)
{
cout << arr[i] << " ";
if ((i + 1) % 3 == 0)
cout << endl;
}
cout << endl;
}
// this function tests to see if we have a "good" arrangement of numbers
// i.e the sum of each row, column and diagonal is equal
bool checkArr(int arr[])
{
anyLine = arr[0] + arr[1] + arr[2];
currLine = 0;
for (int i = 0; i < SQUARE_SIZE; i++)
{
currLine += arr[i];
if ((i + 1) % 3 == 0)
{
if (currLine != anyLine)
return false;
currLine = 0;
}
}
// check vertically
for (int col = 0; col <3; col++)
{
for (int row = 0; row <3; row++)
{
currLine += arr[col + 3 * row];
}
if (currLine != anyLine)
return false;
currLine = 0;
}
// check the diagonals
if ((arr[2] + arr[4] + arr[6]) != anyLine)
return false;
if ((arr[0] + arr[4] + arr[8]) != anyLine)
return false;
return true;
}
void solve(int arr[], int pos)
{
if (pos == 8)
{
if (checkArr(arr))
{
printArray(arr);
numSolutions++;
}
} else
{
for (int i = 0; i < 9; i++)
{
if (i == pos) continue;
if (checkArr(arr))
{
printArray(arr);
numSolutions++;
}
swap(arr, pos, i);
solve(arr, pos + 1);
}
}
}
int main()
{
int arr[SQUARE_SIZE] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
solve(arr, 0);
cout << "number of solutions is: " << numSolutions << endl;
return 0;
}
Basically, you are finding all permutations of the array using a recursive permutation algorithm.
There are 4 things you need to change:
First, start your loop from pos, not 0
Second, swap elements back after recursing (backtracking)
Third, only test once you have generated each complete permutation (when pos = 8), or else you will be testing the same permutations more than once.
Fourth, swapping an element with itself (i.e. not swapping it) is a valid permutation, because the elements are allowed to stay in their original positions.
void solve(int arr[], int pos)
{
if (pos == 8)
{
if (checkArr(arr))
{
printArray(arr);
numSolutions++;
}
}
else
{
for (int i = pos ; i < 9; i++)
{
swap(arr,pos,i);
solve(arr,pos +1);
swap(arr,pos,i);
}
}
}
Demo
Your code calls printArray from two places - the base case of the recursion (i.e. when pos == 8) and in the loop before calling swap. The second call is unnecessary: you would get the same square when you reach the pos == 8 state.
This brings the number of duplicates down, but it does not eliminate them because of the way in which you generate your squares. You need to keep track of what has been printed. One way to do it is to make a set of solutions that you have found, and check it before printing the newly found solution:
set<int> seen;
int key(int arr[]) {
return arr[0]
+ 10 * arr[1]
+ 100 * arr[2]
+ 1000 * arr[3]
+ 10000 * arr[4]
+ 100000 * arr[5]
+ 1000000 * arr[6]
+ 10000000 * arr[7]
+ 100000000 * arr[8];
}
void printArray(int arr[]) {
if (!seen.insert(key(arr)).second) {
// second is set to false when a duplicate is found
return;
}
numSolutions++;
for (int i = 0; i < SQUARE_SIZE; i++) {
cout << arr[i] << " ";
if((i+1) % 3 == 0)
cout << endl;
}
cout << endl;
}
Demo.
A few things to note about the solution above:
key(int[]) converts the square to a single decimal number, so this approach is going to work only for squares composed of decimal digits. You would need a different strategy for arbitrary numbers - for example, using a set of comma-separated strings.
Counting of solutions is moved to printArray(int[]). You could drop numSolutions altogether, and use seen.size() instead; it provides the same answer.
If you don't want to actually solve this recursively for exercise purposes, I'd recommend using std::next_permutation:
void solve(int(&arr)[SQUARE_SIZE], int pos)
{
sort(std::begin(arr), std::end(arr));
do {
if (checkArr(arr)) {
numSolutions++;
printArray(arr);
}
} while (next_permutation(begin(arr), end(arr)));
}
I am trying to make a program that recieves numbers from the user, and then rearranges the from least to greatest. I am using vectors (which I just learned about), and it gives me a subscript out of range error. I am not able to find what part of the code gives me this error, so hopefully someone more knowledgeable on vector and c++ can find it:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void order(int a, int b);
void orderRev(int a, int b);
int main() {
vector<int> num;
bool going = true;
do {
cout << "\nEnter a number or type 'x' to order:" << endl;
string reply;
getline(cin, reply);
if (reply != "x") {
int a = atoi(reply.c_str());
num.push_back(a);
cout << "\nYou currently have " << num.size() << " numbers added." << endl;
}
else {
going = false;
}
} while (going);
for (int i = 0; i < num.size(); i++) {
order(num[i], num[i + 1]);
}
for (int i = num.size() - 1; i >= 0; i--) {
orderRev(num[i + 1], num[i]);
}
cout << "\nThe number you entered in order from least to greatest are: " << endl;
for (int i = 0; i < num.size(); i++) {
cout << num[i] << " ";
}
void order(int a, int b) {
if (a > b) {
int c = b;
b = a;
a = c;
}
}
void orderRev(int a, int b) {
if (a < b) {
int c = b;
b = a;
a = c;
}
}
Fix these lines to this:
// added the -1 as this will now go up to the 2nd to last element
// for `n`, and the last element for `n+1`
for (int i = 0; i < num.size() - 1; i++) {
order(num[i], num[i + 1]);
}
// changed the starting number to size -2 (for the same reasoning)
for (int i = num.size() - 2; i >= 0; i--) {
orderRev(num[i + 1], num[i]);
}
Why does this need to be this way? Think about how indices in C++ work. They are zero-indexed! That means that if you want both the element and the one in front of it, you must go up to the size of the vector minus 1. Hence, for a vector of 10 items (size 10), at i == 9 your code will work like this:
for (int i = 0; i < num.size(); i++) {
// i = 9
order(num[9], num[9+1]);// index 10 does not exist! Hence, you really need to go up to num.size() - 1!
}
Vectors index start with 0. index will be 0 to n-1 , if you use num[i + 1] it will exceed the vector size, if you don't check in loop condition.
Your code has more than one flaw. The output will be same as the input , hint: know the difference between pass by reference and pass by value and after that check some sorting algorithms.
I was solving a simple problem on spoj called Ambiguous Permutations(http://www.spoj.com/problems/PERMUT2/), it worked fine when I tested for small inputs, but on submission it shows runtime error - segmentation fault. I'm not able to figure it out (though I've wasted a lot of time, and gained frustration only). Please help.
#include <iostream>
#include <stdlib.h>
#include <string.h>
char arr1[200000];//stores original string.
char arr2[200000];//stores inverse permutation.
long int n;
using namespace std;
int main()
{
while (1)
{
cin >> n;
if (n == 0)
{
exit(0);
}
getchar();
gets(arr1);
//creating inverse permutation.
for (long int i = 0; i < 2 * n - 1; i++)
{
if (i % 2 == 1)
{
arr2[i] = ' ';
}
else
{
arr2[2 * (arr1[i] - '0') - 2] = i / 2 + '1';
}
}
arr2[2 * n - 1] = '\0';
//comparing string with it's inverse permutation.
if (strcmp(arr1, arr2) == 0)
{
cout << endl << "ambiguous";
}
else
{
cout << endl << "not ambiguous";
}
}
return 0;
}
The problem is that you are using a char array to represent integers, and your code assumes that each number is represented by one char (note for example checking i % 2 == 1 to determine whether number or space).
Hence, any number bigger than 9 will cause correctness / memory problems.
If you'll use integer arrays it will be a lot easier.
You'll stop worrying about the space character ' ', won't need to decrement '0' char from the cells, and won't need your loops to run till 2 * n - 1.
I think it is much clearer this way:
#include <iostream>
using namespace std;
const int MAX_SIZE = 1000;
int arr1[MAX_SIZE];
int arr2[MAX_SIZE];
int size = 0;
bool areArrsEqual()
{
for (int i = 0; i < size; ++i)
{
if (arr1[i] != arr2[i])
{
return false;
}
}
return true;
}
int main()
{
cin >> size;
while (size > 0 && size <= MAX_SIZE)
{
for (int i = 0; i < size; ++i)
{
cin >> arr1[i];
}
// creating inverse permutation.
for (int i = 0; i < size; i++)
{
// if (arr[i] - 1 >= size) ==> illegal input.
arr2[arr1[i] - 1] = i + 1;
}
// comparing permutation with it's inverse permutation.
if (areArrsEqual())
{
cout << "ambiguous" << endl;
}
else
{
cout << "not ambiguous" << endl;
}
cin >> size;
}
return 0;
}
Output:
4
1 4 3 2
ambiguous
5
2 3 4 5 1
not ambiguous
1
1
ambiguous
13
1 2 3 4 5 6 7 8 9 10 11 12 13
ambiguous
0
According to this post, we can get all divisors of a number through the following codes.
for (int i = 1; i <= num; ++i){
if (num % i == 0)
cout << i << endl;
}
For example, the divisors of number 24 are 1 2 3 4 6 8 12 24.
After searching some related posts, I did not find any good solutions. Is there any efficient way to accomplish this?
My solution:
Find all prime factors of the given number through this solution.
Get all possible combinations of those prime factors.
However, it doesn't seem to be a good one.
Factors are paired. 1 and 24, 2 and 12, 3 and 8, 4 and 6.
An improvement of your algorithm could be to iterate to the square root of num instead of all the way to num, and then calculate the paired factors using num / i.
You should really check till square root of num as sqrt(num) * sqrt(num) = num:
Something on these lines:
int square_root = (int) sqrt(num) + 1;
for (int i = 1; i < square_root; i++) {
if (num % i == 0&&i*i!=num)
cout << i << num/i << endl;
if (num % i == 0&&i*i==num)
cout << i << '\n';
}
There is no efficient way in the sense of algorithmic complexity (an algorithm with polynomial complexity) known in science by now. So iterating until the square root as already suggested is mostly as good as you can be.
Mainly because of this, a large part of the currently used cryptography is based on the assumption that it is very time consuming to compute a prime factorization of any given integer.
Here's my code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
#define pii pair<int, int>
#define MAX 46656
#define LMT 216
#define LEN 4830
#define RNG 100032
unsigned base[MAX / 64], segment[RNG / 64], primes[LEN];
#define sq(x) ((x)*(x))
#define mset(x,v) memset(x,v,sizeof(x))
#define chkC(x,n) (x[n>>6]&(1<<((n>>1)&31)))
#define setC(x,n) (x[n>>6]|=(1<<((n>>1)&31)))
// http://zobayer.blogspot.com/2009/09/segmented-sieve.html
void sieve()
{
unsigned i, j, k;
for (i = 3; i<LMT; i += 2)
if (!chkC(base, i))
for (j = i*i, k = i << 1; j<MAX; j += k)
setC(base, j);
primes[0] = 2;
for (i = 3, j = 1; i<MAX; i += 2)
if (!chkC(base, i))
primes[j++] = i;
}
//http://www.geeksforgeeks.org/print-all-prime-factors-of-a-given-number/
vector <pii> factors;
void primeFactors(int num)
{
int expo = 0;
for (int i = 0; primes[i] <= sqrt(num); i++)
{
expo = 0;
int prime = primes[i];
while (num % prime == 0){
expo++;
num = num / prime;
}
if (expo>0)
factors.push_back(make_pair(prime, expo));
}
if ( num >= 2)
factors.push_back(make_pair(num, 1));
}
vector <int> divisors;
void setDivisors(int n, int i) {
int j, x, k;
for (j = i; j<factors.size(); j++) {
x = factors[j].first * n;
for (k = 0; k<factors[j].second; k++) {
divisors.push_back(x);
setDivisors(x, j + 1);
x *= factors[j].first;
}
}
}
int main() {
sieve();
int n, x, i;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x;
primeFactors(x);
setDivisors(1, 0);
divisors.push_back(1);
sort(divisors.begin(), divisors.end());
cout << divisors.size() << "\n";
for (int j = 0; j < divisors.size(); j++) {
cout << divisors[j] << " ";
}
cout << "\n";
divisors.clear();
factors.clear();
}
}
The first part, sieve() is used to find the prime numbers and put them in primes[] array. Follow the link to find more about that code (bitwise sieve).
The second part primeFactors(x) takes an integer (x) as input and finds out its prime factors and corresponding exponent, and puts them in vector factors[]. For example, primeFactors(12) will populate factors[] in this way:
factors[0].first=2, factors[0].second=2
factors[1].first=3, factors[1].second=1
as 12 = 2^2 * 3^1
The third part setDivisors() recursively calls itself to calculate all the divisors of x, using the vector factors[] and puts them in vector divisors[].
It can calculate divisors of any number which fits in int. Also it is quite fast.
Plenty of good solutions exist for finding all the prime factors of not too large numbers. I just wanted to point out, that once you have them, no computation is required to get all the factors.
if N = p_1^{a}*p_{2}^{b}*p_{3}^{c}.....
Then the number of factors is clearly (a+1)(b+1)(c+1).... since every factor can occur zero up to a times.
e.g. 12 = 2^2*3^1 so it has 3*2 = 6 factors. 1,2,3,4,6,12
======
I originally thought that you just wanted the number of distinct factors. But the same logic applies. You just iterate over the set of numbers corresponding to the possible combinations of exponents.
so int he example above:
00
01
10
11
20
21
gives you the 6 factors.
If you want all divisors to be printed in sorted order
int i;
for(i=1;i*i<n;i++){ /*print all the divisors from 1(inclusive) to
if(n%i==0){ √n (exclusive) */
cout<<i<<" ";
}
}
for( ;i>=1;i--){ /*print all the divisors from √n(inclusive) to
if(n%i==0){ n (inclusive)*/
cout<<(n/i)<<" ";
}
}
If divisors can be printed in any order
for(int j=1;j*j<=n;j++){
if(n%j==0){
cout<<j<<" ";
if(j!=(n/j))
cout<<(n/j)<<" ";
}
}
Both approaches have complexity O(√n)
Here is the Java Implementation of this approach:
public static int countAllFactors(int num)
{
TreeSet<Integer> tree_set = new TreeSet<Integer>();
for (int i = 1; i * i <= num; i+=1)
{
if (num % i == 0)
{
tree_set.add(i);
tree_set.add(num / i);
}
}
System.out.print(tree_set);
return tree_set.size();
}
//Try this,it can find divisors of verrrrrrrrrry big numbers (pretty efficiently :-))
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<conio.h>
using namespace std;
vector<double> D;
void divs(double N);
double mod(double &n1, double &n2);
void push(double N);
void show();
int main()
{
double N;
cout << "\n Enter number: "; cin >> N;
divs(N); // find and push divisors to D
cout << "\n Divisors of "<<N<<": "; show(); // show contents of D (all divisors of N)
_getch(); // used visual studio, if it isn't supported replace it by "getch();"
return(0);
}
void divs(double N)
{
for (double i = 1; i <= sqrt(N); ++i)
{
if (!mod(N, i)) { push(i); if(i*i!=N) push(N / i); }
}
}
double mod(double &n1, double &n2)
{
return(((n1/n2)-floor(n1/n2))*n2);
}
void push(double N)
{
double s = 1, e = D.size(), m = floor((s + e) / 2);
while (s <= e)
{
if (N==D[m-1]) { return; }
else if (N > D[m-1]) { s = m + 1; }
else { e = m - 1; }
m = floor((s + e) / 2);
}
D.insert(D.begin() + m, N);
}
void show()
{
for (double i = 0; i < D.size(); ++i) cout << D[i] << " ";
}
int result_num;
bool flag;
cout << "Number Divisors\n";
for (int number = 1; number <= 35; number++)
{
flag = false;
cout << setw(3) << number << setw(14);
for (int i = 1; i <= number; i++)
{
result_num = number % i;
if (result_num == 0 && flag == true)
{
cout << "," << i;
}
if (result_num == 0 && flag == false)
{
cout << i;
}
flag = true;
}
cout << endl;
}
cout << "Press enter to continue.....";
cin.ignore();
return 0;
}
for (int i = 1; i*i <= num; ++i)
{
if (num % i == 0)
cout << i << endl;
if (num/i!=i)
cout << num/i << endl;
}
for( int i = 1; i * i <= num; i++ )
{
/* upto sqrt is because every divisor after sqrt
is also found when the number is divided by i.
EXAMPLE like if number is 90 when it is divided by 5
then you can also see that 90/5 = 18
where 18 also divides the number.
But when number is a perfect square
then num / i == i therefore only i is the factor
*/
//DIVISORS IN TIME COMPLEXITY sqrt(n)
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
ll int n;
cin >> n;
for(ll i = 2; i <= sqrt(n); i++)
{
if (n%i==0)
{
if (n/i!=i)
cout << i << endl << n/i<< endl;
else
cout << i << endl;
}
}
}
#include<bits/stdc++.h>
using namespace std;
typedef long long int ll;
#define MOD 1000000007
#define fo(i,k,n) for(int i=k;i<=n;++i)
#define endl '\n'
ll etf[1000001];
ll spf[1000001];
void sieve(){
ll i,j;
for(i=0;i<=1000000;i++) {etf[i]=i;spf[i]=i;}
for(i=2;i<=1000000;i++){
if(etf[i]==i){
for(j=i;j<=1000000;j+=i){
etf[j]/=i;
etf[j]*=(i-1);
if(spf[j]==j)spf[j]=i;
}
}
}
}
void primefacto(ll n,vector<pair<ll,ll>>& vec){
ll lastprime = 1,k=0;
while(n>1){
if(lastprime!=spf[n])vec.push_back(make_pair(spf[n],0));
vec[vec.size()-1].second++;
lastprime=spf[n];
n/=spf[n];
}
}
void divisors(vector<pair<ll,ll>>& vec,ll idx,vector<ll>& divs,ll num){
if(idx==vec.size()){
divs.push_back(num);
return;
}
for(ll i=0;i<=vec[idx].second;i++){
divisors(vec,idx+1,divs,num*pow(vec[idx].first,i));
}
}
void solve(){
ll n;
cin>>n;
vector<pair<ll,ll>> vec;
primefacto(n,vec);
vector<ll> divs;
divisors(vec,0,divs,1);
for(auto it=divs.begin();it!=divs.end();it++){
cout<<*it<<endl;
}
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
sieve();
ll t;cin>>t;
while(t--) solve();
return 0;
}
We can use modified sieve for getting all the factors for all numbers in range [1, N-1].
for (int i = 1; i < N; i++) {
for (int j = i; j < N; j += i) {
ans[j].push_back(i);
}
}
The time complexity is O(N * log(N)) as the sum of harmonic series 1 + 1/2 + 1/3 + ... + 1/N can be approximated to log(N).
More info about time complexity : https://math.stackexchange.com/a/3367064
P.S : Usually in programming problems, the task will include several queries where each query represents a different number and hence precalculating the divisors for all numbers in a range at once would be beneficial as the lookup takes O(1) time in that case.
java 8 recursive (works on HackerRank). This method includes option to sum and return the factors as an integer.
static class Calculator implements AdvancedArithmetic {
public int divisorSum(int n) {
if (n == 1)
return 1;
Set<Integer> set = new HashSet<>();
return divisorSum( n, set, 1);
}
private int divisorSum(int n, Set<Integer> sum, int start){
if ( start > n/2 )
return 0;
if (n%start == 0)
sum.add(start);
start++;
divisorSum(n, sum, start);
int total = 0;
for(int number: sum)
total+=number;
return total +n;
}
}
I'm doing an online challenge and the challenge is the following:
"Kids are playing a game called "Counting digits". For given numbers S and K, they firstly write all numbers between those numbers and then count how many times each digit appears (0,1,2,3,4,5,6,7,8,9). For example, S=767, K=772, numbers will be: 767,768,769,770,771,772
So, 0 will show once (in 770), 1 will show once (in 771) and so on..
Basically, my program have to do the following (given example):
Input:
1 9
(These are numbers 1,2,3,4,5,6,7,8,9)
Output:
0 1 1 1 1 1 1 1 1 1
(0 doesn't show, other numbers show once)."
I'm stuck on this code... out of ideas.
#include <iostream>
using namespace std;
int main()
{
int s,k;
int array[10];
int c0=0,c1=0,c2=0,c3=0,c4=0,c5=0,c6=0,c7=0,c8=0,c9=0;
cin >> s >> k;
int saves = s;
int savek = k;
cout << s%10;
for(int i=s;i<=k;i++)
{
int savei=i;
while(savei!=0)
{
savei=savei%10;
}
}
Any pseudo code/snippet/code/hint is appreciated.
Purely numeric solution to a purely numeric problem:
#include <iostream>
int main()
{
int s, k, i, tmp;
std::cin >> s >> k;
int count[10] = { 0 };
for (i = s; i <= k; i++) {
tmp = i;
do {
count[tmp % 10]++;
tmp /= 10;
} while(tmp);
}
for (i = 0; i < 10; i++) {
std::cout << i << " appears " << count[i] << " times" << std::endl;
}
return 0;
}
My solution is like this:
int main(){
int s,k;
cin >> s >> k;
int numbers[10]={0};
string sum;
for(int i=s;i<=k;i++)
{
sum=to_string(i);
for(int i=0;i<sum.length();i++){
numbers[(int)sum.at(i)-48]++;
}
}
for(int i=0;i<10;i++){
cout<<numbers[i]<<endl;
}
return 0;
}
public static void getDigitsInBook(int n) {
for(int i=0;i<10;i++) {
int x = n,val=0,k=1;
while(x!=0) {
int left = x/10;
int num = x%10;
int right = n%k;
if(i == 0) {
val = val+ (left*k);
}
else if(i<num) {
val = val + ((left+1)*k);
}
else if(i==num) {
val = val + (left*k) + right+1;
}
else {
val = val+ (left*k);
}
k=k*10;
x = n/k;
}
System.out.println(val);
}
}
What you usually do with such tasks is calculating the number between 0 and S and between 0 and K and subtracting those.
How many are between 0 and 767? First count the numbers of the last digit. There are 77 times 0, 1, 2, 3, 4, 5, 6, 7 each and 76 times 8 and 9. More formally, 767/10+1 between 0 and 767%10 and 767/10+1 on the rest. Then calculate the number of occurences of the last digit for 767/10=76, multiply by 10, add 7 times 7 and 6 (for the error on the last one) and do the same for the remaining digits, here 76/10=7. Finally, add the results up.
This solves the problem in O(log_10 K).
try this code:
for(int n=s ; n<=k ; n++)
{
tempN = abs(n);
while(tempN > 0)
{
tempDigit = tempN % 10;
tempN /= 10;
//count tempDigit here
}
}
assuming your variables are ints, "tempN /= 10;" should be no problem.