Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
How can I generate all combinations of n elements in groups of k?
For example, takig "abcd" in groups of 3, from [aaa] to [ddd]?
EDIT: What I've "accomplished" so far:
int main (int argc, char * argvc[]) {
int tComb = 0, array[7] = { 48 , 48 , 48 , 48 , 48 , 48 , 48 };
while ( tComb < atoi(argvc[1]) ) {
for (int i = 6 ; i>0 ; i--) {
if (array[i] == 58)
array[i] = 65;
if (array[i] == 91)
array[i] = 97;
if (array[i] == 123){
array[i] = 48;
array[i-1]++;
}
}
std::cout << "Current Combination: ";
std::cout << array;
std::cout << "\n";
tComb++;
array[6]++;
}
}
It'll try and generate backward the latest combination of alphanumeric characters, but it's hardcoded and won't work well.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned powu(unsigned base, unsigned exp){
unsigned result = 1;
while(exp > 0){
if(exp & 1)
result *= base;
base = base * base;
exp >>=1;
}
return result;
}
int main(int argc, char *argv[]){
if(argc != 3){
fprintf(stderr, "Usage : RepeatedPermutation abcd 3\n");
return -1;
}
char *list = argv[1];
unsigned gp_len = atoi(argv[2]);
unsigned list_len = strlen(list);
char *gp = calloc(gp_len+1, sizeof(char));
int total_n = powu(list_len, gp_len);
int i, j;
for(i=0;i<total_n;++i){
int n = i;
for(j=0;j<gp_len;++j){
gp[gp_len -j -1] = list[n % list_len];
n /= list_len;
}
printf("[%s]\n", gp);
}
free(gp);
return 0;
}
Am not sure but i think this is the answer to your question. If you want three groups than you should have 3 different loops.Its pretty simple when you see the output of this program.
You just need to increment the value of what ever you want to generate there possible combination.
The below Code will generate all possible combination of "abcd" in groups of 3, from [aaa] to [ddd].
int main()
{
char ch1;
char ch2;
char ch3;
for(ch1='a';ch1<='d';ch1++)
{
for(ch2='a';ch2<='d';ch2++)
{
for(ch3='a';ch3<='d';ch3++)
{
printf("%c %c %c\n",ch1,ch2,ch3);
}
printf("\n"); //just to have clean and understandable output
}
printf("\n\n\n"); //just to have clean and understandable output
}
return 0;
}
One method to generate all the combinations is to treat this as a number counting program.
The Counting Algorithm
Let's take the case of "digits": a, b, c, and d.
The first number is: aaaa. Much like decimal: 0000.
The second number is: aaab. Decimal: 0001.
The third number is: aaac, decimal: 0002.
The fourth number is: aaad, decimal: 0003.
This process is known as incrementing, e.g. adding a constant value each time.
Now comes the tricky part, incrementing the last digit. According to number counting rules, when the last digit is reached, the last digit is replaced by the first and the digit in the next column is replaced. This is equivalent of a decimal number incrementing from 09 to 10.
So in the example above, the next number in the sequence is: aaba.
This is known as carry, as you are carrying the overflow to the next digit.
Converting Algorithm to Code
Looks like there is a loop to count from first digit to last digit:
#define MAXIMUM_DIGIT_POSITIONS 4
const char FIRST_CHAR = 'a';
const char LAST_CHAR = 'd';
std::vector<char> number(MAXIMUM_DIGIT_POSITIONS); // Reserve some slots.
void Print_Number(const std::vector<char>& number);
int main(void)
{
// Initialize the number
int position = 0;
for (position = 0; position < MAXIMUM_DIGIT_POSITIONS; ++position)
{
number.push_back(FIRST_CHAR);
}
Print_Number(number);
// Loop: incrementing
position = MAXIMUM_DIGIT_POSITIONS - 1; // Because arrays are zero based indexing
while (number[position] < LAST_CHAR)
{
number[position] = number[position] + 1; // Increment to next digit, same position.
Print_Number(number);
}
// Pause before closing
std::cout << "Paused. Press ENTER to close.\n";
std::cin.ignore(100000, '\n');
return EXIT_SUCCESS;
}
void Print_Number(const std::vector<char>& number)
{
for (std::vector<char>::const_iter iter = number.begin();
iter != number.end();
++iter)
{
std::cout << *iter;
}
cout << "\n";
}
Handling Carry
The above program demonstrates counting in a single column. But how to handle the incrementing of the last digit?
Looks like we need to increment the digit in the previous position.
Looking ahead, the value in the previous column will be incremented, until it too, needs to be increment. Thus the carry will be propagate to the previous column. Looks like another loop:
// Loop: number of positions
int propagation_position = position - 1;
while (propagation_position >= 0)
{
while (number[position] < LAST_CHAR)
{
number[position] = number[position] + 1; // Increment to next digit, same position.
Print_Number(number);
}
// Propagate the carry.
while (propagation_position >= 0)
{
if (number[propagation_position] != LAST_CHAR)
{
++number[propagation_position];
number[propagation_position + 1] = FIRST_CHAR;
break;
}
--propagation_position;
}
position = 0;
}
The above new fragment has an outer while loop and a second inner while loop. The outer while loop controls the digit position. The second inner while loop handles the carry.
The whole program is designed so that you can adjust the number of digit positions and the number of digits in the sequence.
Summary
The brute force method for printing all the combinations is like counting numbers. The same principles apply: when the last digit is incremented, it is replaced by the first digit and the digit of the next column is incremented. This is repeated until all positions have been counted.
Walk through the above code with debugger or pen and paper to find any defects and understand the algorithm.
After you understand the algorithm, search your favorite C++ reference for "c++ combination permutation algorithm".
Related
The Problem:
A company is distributing phone numbers to its employees to make things easier. the next digit cannot be equal to the last is the only rule for example 0223 is not allowed while 2023 is allowed. At least three digits will be excluded every time. Write a function that takes in a length of the phone number and the digits that will be excluded. The function should print all possible phone numbers.
I got this question in an interview and I have seen one like it before at my university. It is a permutation problem. My question is what is the best way or decent way to solve this without a million for loops.
I do understand that this is technically how it works
length of phone number = 3;
[0-9], [0-9] excluding the last digit, [0-9] excluding the last digit
but I am unsure on how the best way to turn this into code. Any language is accepted!
thank you:
Also I might be asking this in the wrong place. please let me know if I am.
A simple way to solve this problem could be using Recursion. Here's my commented C++ code:
void solve(int depth, int size, vector <int> &curr_seq){
// If the recursion depth is equal to size, that means we've decided size
// numbers, which means that curr_seq.size() == size. In other words, we've
// decided enough numbers at this point to create a complete phone number, so
// we print it and return.
if(depth == size){
for(int item : curr_seq){
cout << item;
}
cout << "\n";
return;
}
// Try appending every possible digit to the current phone number
for(int i = 0; i <= 9; ++i){
// Make sure to only append the digit i if it is not equal to the last digit
// of the phone number. We can also append it, however, if curr_seq
// is empty (because that means that we haven't decided the 1st digit yet).
if(curr_seq.empty() || curr[curr.size() - 1] != i){
curr_seq.push_back(i);
solve(depth + 1, size, curr);
curr_seq.pop_back();
}
}
}
I think I like the recursive solution, but you can also just generate all permutations up to the limit (iterate), filter out any with repeating digits, and print the successful candidates:
#include <iomanip>
#include <iostream>
#include <sstream>
using namespace std;
// Because C/C++ still has no integer power function.
int ipow(int base, int exp) {
int result = 1;
for (;;) {
if (exp & 1)
result *= base;
exp >>= 1;
if (!exp)
return result;
base *= base;
}
}
void noconsec(const int len) {
int lim = ipow(10, len);
// For e.g. len 4 (lim 10000),
// obviously 00xx won't work, so skip anything smaller than lim / 100.
int start = (len <= 2) ? 0 : (lim / 100);
for (int num = start;num < lim;num++) {
// Convert to string.
std::stringstream ss;
ss << std::setw(len) << std::setfill('0') << num;
std::string num_s = ss.str();
// Skip any consecutive digits.
bool is_okay = true;
auto prev_digit = num_s[0];
for (int digit_idx = 1;digit_idx < num_s.length();digit_idx++) {
auto digit = num_s[digit_idx];
if (prev_digit == digit) {
is_okay = false;
}
prev_digit = digit;
}
// Output result.
if (is_okay) {
cout << num_s << "\n";
}
}
}
int main(const int argc, const char * const argv[]) {
noconsec(4);
}
Differences to note, this needs an integer power function to compute the limit. Converting an int to a string and then checking the string is more complex than constructing the string directly. I guess it could be useful if you have a list of integers already, but mostly I did it for fun.
Disclaimer: This question is more of a challenge, and the post is also quite long. Read only in free time!
The Problem:
Basically, suppose there is a single line of integer inputs:
32352\n // assuming single digits only and no spaces for simplification
We have to remove duplicates from the inputs, and then display them. So, output should be:
After removing duplicates: 2, 3, 5 // display them in any order
However, there is a catch:
Do not use any data structures containers.
Edit: I believe containers are what I meant (thanks Vlad!).
So, my question is: What is the error in my implementation, and is there another (better) way to do it?
My thought process:
Since we are not allowed use of any data structure, we cannot store the inputs (I think?).
However, since it is already stored in memory on input, that is not a problem.
More of a problem is removing the duplicates. We will have to manipulate the input stream.
The first thing that struck me is that we can sort the inputs. That is,
32352
becomes:
22335
And now, simply print the first element of each range.
Working on this idea, I came across the std::cin.get() and std::cin.putback() methods, both accepting a char.
I also realized I would have to use recursion.
And hence, the code becomes (I have used insertion sort):
The Code:
The sort() function is where the error is. It uses a running index ala arrays, and this is used to uniquely identify each element.
In each iteration, the index_of_element element is found and selected, and we determine where in the remaining (virtual) array, we need to place it. For example, if in our original input:
32352 // S = sorted subarray
SU--U // U = unsorted subarray
, the first 2 is selected, we "shift" 3 (as 3 < 2).
Now, there are no more elements left to shift, we "place" 2.
The result should become:
23352
SSU-U
The (buggy) implementation:
bool sort(int index_of_element, int index = 0, char prev_element = 0)
{
static char element;
char digit;
// retrieve an element from memory
std::cin.get(digit);
// If not end of input
if(digit != '\n')
{
// store the element for comparision
if(index == index_of_element)
{
element = digit;
}
// continue forward until '\n'
bool result = sort(index_of_element, index + 1, digit);
// if we are in sorted subarray
if(index <= index_of_element)
{
// If element belongs here(also if this is first element(prev_element is 0)), place it
if(element > prev_element)
{
digit = element;
// Signal that element has been placed
element = 0;
}
// Else, if element not already placed, we need to shift elements
else if(element != 0)
{
// Place the previous element here
digit = prev_element;
}
}
// Put it back in memory
std::cin.putback(digit);
// And return the result
return result;
}
// Which is generated here when end of input is reached
else
{
// If sorted all elements, break loop
if(index_of_element == index)
{
return false;
}
// Else, continue sorting
else
{
return true;
}
}
}
(A wall of code, but I didn't want to skip anything relevant), and it should be used as:
...
int index_of_element = 0;
while(sort(index_of_element++));
...
The display function is ready, and it works properly.
What I do know is that it gets stuck in an infinite loop and the values are lost.
What is going wrong?
And should I add the output (The post is already very long)?
The problem seems to be that you don't put the newline back into the stream, while your code assumes that it will be there.
That is, after your first pass, digit != '\n' is always true.
Put the newline back into the stream, or break when you've reached the true end-of-stream.
(There could also be problems with (ab)using std::cin like this, but I'm not sure, and that's another matter anyway.)
You can do it with only function objects, in a single pass.
#include <iostream>
#include <sstream>
#include <functional>
void print_unique_ints(std::istream & in, std::ostream & out, std::function<bool(int)> unseen) {
for (int i; in >> i;) {
if (unseen(i)) {
out << i << ' ';
print_unique_ints(in, out, [&](int j){ return (i != j) && unseen(j); });
return; // not actually needed, previous call only ends when input is exhausted
}
}
}
int main() {
print_unique_ints(std::cin, std::cout, [](int){ return true; });
}
See it live
Each call to print_unique_ints skips previously seen ints, prints the unseen int, and adds to the filter
Substituting values for variables; and function calls for expressions; in the first call
for (int i; in >> i;) { // i = 3
if (true) {
out << 3 << ' ';
print_unique_ints(...) // see below
}
}
The second
for (int i; in >> i;) { // i = 2
if ((3 != i) && true) {
out << 2 << ' ';
print_unique_ints(...) // see below
}
}
The third
for (int i; in >> i;) { // i = 3, 5
if ((2 != i) && (3 != i) && true) { // skips over the 3
out << 5 << ' ';
print_unique_ints(...) // see below
}
}
The forth
for (int i; in >> i;) { // i = 2
if ((5 != i) && (2 != i) && (3 != i) && true) { // skips the 2 and finds the end of input
}
}
Note that && true never changes the result in the if
A variation of bitset (or mask) implem...using the commutative property of multiplication
Take a function f which maps every digit to a unique prime p_i
0 1 2 3 4 5 6 7 8 9
2,3,5,7,9,11,13,17,19,23
If all numbers are found the total amount to N=2*3*5*7*9*11*13*17*19*23=2007835830
Consume cin as c, if f(c) divides N, print c and update N /= f(c)
#include <iostream>
#include <sstream>
int f(char c){
if(c=='0') return 2;
if(c=='1') return 3;
if(c=='2') return 5;
if(c=='3') return 7;
if(c=='4') return 9;
if(c=='5') return 11;
if(c=='6') return 13;
if(c=='7') return 17;
if(c=='8') return 19;
if(c=='9') return 23;
}
int main() {
std::istringstream in("2 2 2 3 5");
int N = 2007835830;
char c;
while(in >> c){
if(c=='\n') break;
int p_i = f(c);
if(N % p_i == 0){
N = N/p_i;
std::cout<<c<<" ";
}
}
}
I am sure that this phrase
Remove duplicates from input without use of any data structures
means that you shall not use any container like for example std::string or an ordinary array.
The assignment is not simple for a beginner.
Here are my five cents.
#include <iostream>
#include <type_traits>
template <typename T>
T remove_duplicates( T n )
{
static_assert ( std::is_integral<T>::value );
const T Base = 10;
T result = n % Base;
for ( T multiplier = 1; n /= Base; )
{
T digit = n % Base;
T tmp = result;
bool unique = true;
while ( ( unique = tmp % Base != digit ) && ( tmp /= Base ) );
if ( unique )
{
multiplier *= Base;
result = digit == 0 ? result * multiplier + digit
: digit * multiplier + result;
}
}
return result;
}
int main()
{
for ( int n : { 0, 1, 10, 101, 100, 10203, -1, -10, -101, -100, - 10203 } )
{
std::cout << n << ": " << remove_duplicates( n ) << '\n';
}
return 0;
}
The program output is
0: 0
1: 1
10: 10
101: 10
100: 10
10203: 1230
-1: -1
-10: -10
-101: -10
-100: -10
-10203: -1230
That is you are building a new number from the source number by checking whether the new number already contains a digit from the source number.
The function can work with any integer type signed or unsigned. It correctly processes digits equal to 0.
It was said not to use any arrays, vectors, stacks, queues etc and neither our own implementations of it. I simplified the condition.
Well I've got bad news for you; this is not possible.
Given an input of length N you will need to somehow remember the previous N - 1 values to decide whether to print the Nth value or not. This is not possible with constant space.
So you need some data structure.
Now ...
Since we are not allowed use of any data structure, we cannot store the inputs (I think?).
However, since it is already stored in memory on input, that is not a problem.
So let's assume the existence of a (mutable) array of length N, containing the input values. Now we can solve this without using additional storage / data structures:
Select some value as special value
Iterate over the numbers until you find a value which is not that special value. print that value. Write the special value to the array where you found the value you just printed. finish iterating over the numbers, overwritte each occurrence of the just printed value with the special value.
repeat (from 2) until the input consists only of special values.
You just need to think about a way to handle the case where the special value was present in the input from the start.
I am writing code to get the last digit of very large fibonacci numbers such as fib(239), etc.. I am using strings to store the numbers, grabbing the individual chars from end to beginning and then converting them to int and than storing the values back into another string. I have not been able to test what I have written because my program keeps abruptly closing after the std::cin >> n; line.
Here is what I have so far.
#include <iostream>
#include <string>
using std::cin;
using std::cout;
using namespace std;
char get_fibonacci_last_digit_naive(int n) {
cout << "in func";
if (n <= 1)
return (char)n;
string previous= "0";
string current= "1";
for (int i = 0; i < n - 1; ++i) {
//long long tmp_previous = previous;
string tmp_previous= previous;
previous = current;
//current = tmp_previous + current; // could also use previous instead of current
// for with the current length of the longest of the two strings
//iterates from the end of the string to the front
for (int j=current.length(); j>=0; --j) {
// grab consectutive positions in the strings & convert them to integers
int t;
if (tmp_previous.at(j) == '\0')
// tmp_previous is empty use 0 instead
t=0;
else
t = stoi((string&)(tmp_previous.at(j)));
int c = stoi((string&)(current.at(j)));
// add the integers together
int valueAtJ= t+c;
// store the value into the equivalent position in current
current.at(j) = (char)(valueAtJ);
}
cout << current << ":current value";
}
return current[current.length()-1];
}
int main() {
int n;
std::cin >> n;
//char& c = get_fibonacci_last_digit_naive(n); // reference to a local variable returned WARNING
// http://stackoverflow.com/questions/4643713/c-returning-reference-to-local-variable
cout << "before call";
char c = get_fibonacci_last_digit_naive(n);
std::cout << c << '\n';
return 0;
}
The output is consistently the same. No matter what I enter for n, the output is always the same. This is the line I used to run the code and its output.
$ g++ -pipe -O2 -std=c++14 fibonacci_last_digit.cpp -lm
$ ./a.exe
10
There is a newline after the 10 and the 10 is what I input for n.
I appreciate any help. And happy holidays!
I'm posting this because your understanding of the problem seems to be taking a backseat to the choice of solution you're attempting to deploy. This is an example of an XY Problem, a problem where the choice of solution method and problems or roadblocks with its implementation obfuscates the actual problem you're trying to solve.
You are trying to calculate the final digit of the Nth Fibonacci number, where N could be gregarious. The basic understanding of the fibonacci sequence tells you that
fib(0) = 0
fib(1) = 1
fib(n) = fib(n-1) + fib(n-2), for all n larger than 1.
The iterative solution to solving fib(N) for its value would be:
unsigned fib(unsigned n)
{
if (n <= 1)
return n;
unsigned previous = 0;
unsigned current = 1;
for (int i=1; i<n; ++i)
{
unsigned value = previous + current;
previous = current;
current = value;
}
return current;
}
which is all well and good, but will obviously overflow once N causes an overflow of the storage capabilities of our chosen data type (in the above case, unsigned on most 32bit platforms will overflow after a mere 47 iterations).
But we don't need the actual fib values for each iteration. We only need the last digit of each iteration. Well, the base-10 last-digit is easy enough to get from any unsigned value. For our example, simply replace this:
current = value;
with this:
current = value % 10;
giving us a near-identical algorithm, but one that only "remembers" the last digit on each iteration:
unsigned fib_last_digit(unsigned n)
{
if (n <= 1)
return n;
unsigned previous = 0;
unsigned current = 1;
for (int i=1; i<n; ++i)
{
unsigned value = previous + current;
previous = current;
current = value % 10; // HERE
}
return current;
}
Now current always holds the single last digit of the prior sum, whether that prior sum exceeded 10 or not really isn't relevant to us. Once we have that the next iteration can use it to calculate the sum of two single positive digits, which cannot exceed 18, and again, we only need the last digit from that for the next iteration, etc.. This continues until we iterate however many times requested, and when finished, the final answer will present itself.
Validation
We know the first 20 or so fibonacci numbers look like this, run through fib:
0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:13
8:21
9:34
10:55
11:89
12:144
13:233
14:377
15:610
16:987
17:1597
18:2584
19:4181
20:6765
Here's what we get when we run the algorithm through fib_last_digit instead:
0:0
1:1
2:1
3:2
4:3
5:5
6:8
7:3
8:1
9:4
10:5
11:9
12:4
13:3
14:7
15:0
16:7
17:7
18:4
19:1
20:5
That should give you a budding sense of confidence this is likely the algorithm you seek, and you can forego the string manipulations entirely.
Running this code on a Mac I get:
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string before callin funcAbort trap: 6
The most obvious problem with the code itself is in the following line:
for (int j=current.length(); j>=0; --j) {
Reasons:
If you are doing things like current.at(j), this will crash immediately. For example, the string "blah" has length 4, but there is no character at position 4.
The length of tmp_previous may be different from current. Calling tmp_previous.at(j) will crash when you go from 8 to 13 for example.
Additionally, as others have pointed out, if the the only thing you're interested in is the last digit, you do not need to go through the trouble of looping through every digit of every number. The trick here is to only remember the last digit of previous and current, so large numbers are never a problem and you don't have to do things like stoi.
As an alternative to a previous answer would be the string addition.
I tested it with the fibonacci number of 100000 and it works fine in just a few seconds. Working only with the last digit solves your problem for even larger numbers for sure. for all of you requiring the fibonacci number as well, here an algorithm:
std::string str_add(std::string a, std::string b)
{
// http://ideone.com/o7wLTt
size_t n = max(a.size(), b.size());
if (n > a.size()) {
a = string(n-a.size(), '0') + a;
}
if (n > b.size()) {
b = string(n-b.size(), '0') + b;
}
string result(n + 1, '0');
char carry = 0;
std::transform(a.rbegin(), a.rend(), b.rbegin(), result.rbegin(), [&carry](char x, char y)
{
char z = (x - '0') + (y - '0') + carry;
if (z > 9) {
carry = 1;
z -= 10;
} else {
carry = 0;
}
return z + '0';
});
result[0] = carry + '0';
n = result.find_first_not_of("0");
if (n != string::npos) {
result = result.substr(n);
}
return result;
}
std::string str_fib(size_t i)
{
std::string n1 = "0";
std::string n2 = "1";
for (size_t idx = 0; idx < i; ++idx) {
const std::string f = str_add(n1, n2);
n1 = n2;
n2 = f;
}
return n1;
}
int main() {
const size_t i = 100000;
const std::string f = str_fib(i);
if (!f.empty()) {
std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << f[f.size() - 1] << std::endl;
}
std::cin.sync(); std::cin.get();
return 0;
}
Try it with first calculating the fibonacci number and then converting the int to a std::string using std::to_string(). in the following you can extract the last digit using the [] operator on the last index.
int fib(int i)
{
int number = 1;
if (i > 2) {
number = fib(i - 1) + fib(i - 2);
}
return number;
}
int main() {
const int i = 10;
const int f = fib(i);
const std::string s = std::to_string(f);
if (!s.empty()) {
std::cout << "fibonacci of " << i << " = " << f << " | last digit: " << s[s.size() - 1] << std::endl;
}
std::cin.sync(); std::cin.get();
return 0;
}
Avoid duplicates of the using keyword using.
Also consider switching from int to long or long long when your numbers get bigger. Since the fibonacci numbers are positive, also use unsigned.
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.
I am currently working on a basic program which converts a binary number to an octal. Its task is to print a table with all the numbers between 0-256, with their binary, octal and hexadecimal equivalent. The task requires me only to use my own code (i.e. using loops etc and not in-built functions). The code I have made (it is quite messy at the moment) is as following (this is only a snippit):
int counter = ceil(log10(fabs(binaryValue)+1));
int iter;
if (counter%3 == 0)
{
iter = counter/3;
}
else if (counter%3 != 0)
{
iter = ceil((counter/3));
}
c = binaryValue;
for (int h = 0; h < iter; h++)
{
tempOctal = c%1000;
c /= 1000;
int count = ceil(log10(fabs(tempOctal)+1));
for (int counter = 0; counter < count; counter++)
{
if (tempOctal%10 != 0)
{
e = pow(2.0, counter);
tempDecimal += e;
}
tempOctal /= 10;
}
octalValue += (tempDecimal * pow(10.0, h));
}
The output is completely wrong. When for example the binary code is 1111 (decimal value 15), it outputs 7. I can understand why this happens (the last three digits in the binary number, 111, is 7 in decimal format), but can't be able to identify the problem in the code. Any ideas?
Edit: After some debugging and testing I figured the answer.
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
while (true)
{
int binaryValue, c, tempOctal, tempDecimal, octalValue = 0, e;
cout << "Enter a binary number to convert to octal: ";
cin >> binaryValue;
int counter = ceil(log10(binaryValue+1));
cout << "Counter " << counter << endl;
int iter;
if (counter%3 == 0)
{
iter = counter/3;
}
else if (counter%3 != 0)
{
iter = (counter/3)+1;
}
cout << "Iterations " << iter << endl;
c = binaryValue;
cout << "C " << c << endl;
for (int h = 0; h < iter; h++)
{
tempOctal = c%1000;
cout << "3 digit binary part " << tempOctal << endl;
int count = ceil(log10(tempOctal+1));
cout << "Digits " << count << endl;
tempDecimal = 0;
for (int counterr = 0; counterr < count; counterr++)
{
if (tempOctal%10 != 0)
{
e = pow(2.0, counterr);
tempDecimal += e;
cout << "Temp Decimal value 0-7 " << tempDecimal << endl;
}
tempOctal /= 10;
}
octalValue += (tempDecimal * pow(10.0, h));
cout << "Octal Value " << octalValue << endl;
c /= 1000;
}
cout << "Final Octal Value: " << octalValue << endl;
}
system("pause");
return 0;
}
This looks overly complex. There's no need to involve floating-point math, and it can very probably introduce problems.
Of course, the obvious solution is to use a pre-existing function to do this (like { char buf[32]; snprintf(buf, sizeof buf, "%o", binaryValue); } and be done, but if you really want to do it "by hand", you should look into using bit-operations:
Use binaryValue & 3 to mask out the three lowest bits. These will be your next octal digit (three bits is 0..7, which is one octal digit).
use binaryValue >>= 3 to shift the number to get three new bits into the lowest position
Reverse the number afterwards, or (if possible) start from the end of the string buffer and emit digits backwards
It don't understand your code; it seems far too complicated. But one
thing is sure, if you are converting an internal representation into
octal, you're going to have to divide by 8 somewhere, and do a % 8
somewhere. And I don't see them. On the other hand, I see a both
operations with both 10 and 1000, neither of which should be present.
For starters, you might want to write a simple function which converts
a value (preferably an unsigned of some type—get unsigned
right before worrying about the sign) to a string using any base, e.g.:
//! \pre
//! base >= 2 && base < 36
//!
//! Digits are 0-9, then A-Z.
std::string convert(unsigned value, unsigned base);
This shouldn't take more than about 5 or 6 lines of code. But attention,
the normal algorithm generates the digits in reverse order: if you're
using std::string, the simplest solution is to push_back each digit,
then call std::reverse at the end, before returning it. Otherwise: a
C style char[] works well, provided that you make it large enough.
(sizeof(unsigned) * CHAR_BITS + 2 is more than enough, even for
signed, and even with a '\0' at the end, which you won't need if you
return a string.) Just initialize the pointer to buffer +
sizeof(buffer), and pre-decrement each time you insert a digit. To
construct the string you return:
std::string( pointer, buffer + sizeof(buffer) ) should do the trick.
As for the loop, the end condition could simply be value == 0.
(You'll be dividing value by base each time through, so you're
guaranteed to reach this condition.) If you use a do ... while,
rather than just a while, you're also guaranteed at least one digit in
the output.
(It would have been a lot easier for me to just post the code, but since
this is obviously homework, I think it better to just give indications
concerning what needs to be done.)
Edit: I've added my implementation, and some comments on your new
code:
First for the comments: there's a very misleading prompt: "Enter a
binary number" sounds like the user should enter binary; if you're
reading into an int, the value input should be decimal. And there are
still the % 1000 and / 1000 and % 10 and / 10 that I don't
understand. Whatever you're doing, it can't be right if there's no %
8 and / 8. Try it: input "128", for example, and see what you get.
If you're trying to input binary, then you really have to input a
string, and parse it yourself.
My code for the conversion itself would be:
//! \pre
//! base >= 2 && base <= 36
//!
//! Digits are 0-9, then A-Z.
std::string toString( unsigned value, unsigned base )
{
assert( base >= 2 && base <= 36 );
static char const digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char buffer[sizeof(unsigned) * CHAR_BIT];
char* dst = buffer + sizeof(buffer);
do
{
*--dst = digits[value % base];
value /= base;
} while (value != 0);
return std::string(dst, buffer + sizeof(buffer));
}
If you want to parse input (e.g. for binary), then something like the
following should do the trick:
unsigned fromString( std::string const& value, unsigned base )
{
assert( base >= 2 && base <= 36 );
static char const digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
unsigned results = 0;
for (std::string::const_iterator iter = value.begin();
iter != value.end();
++ iter)
{
unsigned digit = std::find
( digits, digits + sizeof(digits) - 1,
toupper(static_cast<unsigned char>( *iter ) ) ) - digits;
if ( digit >= base )
throw std::runtime_error( "Illegal character" );
if ( results >= UINT_MAX / base
&& (results > UINT_MAX / base || digit > UINT_MAX % base) )
throw std::runtime_error( "Overflow" );
results = base * results + digit;
}
return results;
}
It's more complicated than toString because it has to handle all sorts
of possible error conditions. It's also still probably simpler than you
need; you probably want to trim blanks, etc., as well (or even ignore
them: entering 01000000 is more error prone than 0100 0000).
(Also, the end iterator for find has a - 1 because of the trailing
'\0' the compiler inserts into digits.)
Actually I don't understand why do you need so complex code to accomplish what you need.
First of all there is no such a thing as conversion from binary to octal (same is true for converting to/from decimal and etc.). The machine always works in binary, there's nothing you can (or should) do about this.
This is actually a question of formatting. That is, how do you print a number as octal, and how do you parse the textual representation of the octal number.
Edit:
You may use the following code for printing a number in any base:
const int PRINT_NUM_TXT_MAX = 33; // worst-case for binary
void PrintNumberInBase(unsigned int val, int base, PSTR szBuf)
{
// calculate the number of digits
int digits = 0;
for (unsigned int x = val; x; digits++)
x /= base;
if (digits < 1)
digits = 1; // will emit zero
// Print the value from right to left
szBuf[digits] = 0; // zero-term
while (digits--)
{
int dig = val % base;
val /= base;
char ch = (dig <= 9) ?
('0' + dig) :
('a' + dig - 0xa);
szBuf[digits] = ch;
}
}
Example:
char sz[PRINT_NUM_TXT_MAX];
PrintNumberInBase(19, 8, sz);
The code the OP is asking to produce is what your scientific calculator would do when you want a number in a different base.
I think your algorithm is wrong. Just looking over it, I see a function that is squared towards the end. why? There is a simple mathematical way to do what you are talking about. Once you get the math part, then you can convert it to code.
If you had pencil and paper, and no calculator (similar to not using pre built functions), the method is to take the base you are in, change it to base 10, then change to the base you require. In your case that would be base 8, to base 10, to base 2.
This should get you started. All you really need are if/else statements with modulus to get the remainders.
http://www.purplemath.com/modules/numbbase3.htm
Then you have to figure out how to get your desired output. Maybe store the remainders in an array or output to a txt file.
(For problems like this is the reason why I want to double major with applied math)
Since you want conversion from decimal 0-256, it would be easiest to make functions, say call them int binary(), char hex(), and int octal(). Do the binary and octal first as that would be the easiest since they can represented by only integers.
#include <cmath>
#include <iostream>
#include <string>
#include <cstring>
#include <cctype>
#include <cstdlib>
using namespace std;
char* toBinary(char* doubleDigit)
{
int digit = atoi(doubleDigit);
char* binary = new char();
int x = 0 ;
binary[x]='(';
//int tempDigit = digit;
int k=1;
for(int i = 9 ; digit != 0; i--)
{
k=1;//cout << digit << endl;
//cout << "i"<< i<<endl;
if(digit-k *pow(8,i)>=0)
{
k =1;
cout << "i" << i << endl;
cout << k*pow(8,i)<< endl;
while((k*pow(8,i)<=digit))
{
//cout << k <<endl;
k++;
}
k= k-1;
digit = digit -k*pow(8,i);
binary[x+1]= k+'0';
binary[x+2]= '*';
binary[x+3]= '8';
binary[x+4]='^';
binary[x+5]=i+'0';
binary[x+6]='+';
x+=6;
}
}
binary[x]=')';
return binary;
}
int main()
{
char value[6]={'4','0','9','8','7','9'};
cout<< toBinary(value);
return 0 ;
}