below is the problem i am given, after this i explain where i am at so far and the code i have created,
Write the following functions in Scheme:

1.a "digitinc4" -takes as input a 4-digit integer, and returns another 4-digit integer constructed of the original input integer's digits, each incremented. For example, (digitinc4 4833) would return 5944. When a digit is a 9, the corresponding output digit should be a 0. For example:
(digitinc4 4892) would return 5903. You can assume that the input number is at least 1000 - that is, there are no leading zeros.

b. Extend your answer in problem (a), above, to handle input integers with an arbitrary number of digits. This function should be named "digitinc" (without the "4" in the name). For example:
(digitinc 83) would return 94, and (digitinc 22897) would return 33908.

so far i know i can increment each digit by adding by
+1
+10
+100
+1000
etc

and as an example

The following results are the remainders which also correspond to the digit I would test:
assuming input is 4816

1st digit
4816 % 10 = 6 (does not equal 0, increment next digit)
2nd digit
4816 / 10 = 481.6
481.6 % 10 = 1 (does not equal 0, increment next digit)
3rd digit
481.6 / 10 = 48.16
48.16 % 10 = 8 (does not equal 0, increment next digit)
4th digit
48.16 / 10 = 4.816
4.816 % 10 = 4 (does not equal 0, increment next digit)

And I can use these remainders to determine if something is a 0
After incrementing that digit, then I can skip the next digit increment

there are some special situations when a digit will become 0 if it was a 9 added by 1. (because 9+1 = 10)
so i can check if this digit is zero (after the addition) to know to skip the next digit addition using
mod: 4816+1 >>>> 4817 % 10 does not equal zero. so i know the digit is not zero so i can continue to add +10
this is a situation where mod is used:
4819+1 >>>> 4820 % 10 = 0 so i know i can now skip +10 and add +100 (because i dont want to increment a digit twice

based on this i have generated some code which runs yet does not perfrom desirable results.
everything works as predicted until the end of the first cond.
by the second cond, at the first test, the debugger says that 2408/5 is happening.
i am totally lost here i have debugged many times but drracket is not sophisticated enough to give me more details.
please if someone could share some insight or advice on this situation or maybe how i could implement what i have in a simpler more efficient way.

and here is my scheme code below:

(define (mod x)
  (modulo x 10))

(define (di4 n)
  (+ n 1) ; increment 1st digit
  (cond ;check if 1st digit became 0 if so skip and increment 100 otherwise continue normal
    [(= (mod n) 0) (+ n 100)] ;increment 3rd if 2nd is 0
    [else (+ n 10)]) ;increment 2nd digit
  (cond
    [(= (mod (/ n 10)) (+ n 1000))] ;increment 4th if 3rd is 0
    [else (+ n 100)]) ;increment 3rd
  (cond
    [(= (mod (/ n 100) (+ n 10000)))] ;increment 5th if 4th is 0
    [else (+ n 1000)]) ;increment 4th
  )

Recommended Answers

All 10 Replies

One quick way to handle this, that easily extends to 'integers' of any length, is to input your numbers as strings ...

and then to code a function to increment each 'digit' in this string as proscribed ...

with a carry term to the 'next left' digit for the case of the incremented 'digit value' becoming 10.

I could show you an example coded in C, C++, Python or Java?

For now, you might like to look at a BIG INT demo that uses strings as 'numbers':

http://developers-heaven.net/forum/index.php/topic,426.0.html

In Python, that easily handles for you, values of type int, to be any length,
you might simply code like this:

# incrementEachDigit.py #  # 2016-10-28 #

def takeInValid4Dig():
    while True:
        try:
            i = int(input( "Enter a 4 digit int between 1000 and 9999: " ))
            if 1000 <= i <= 9999:
                return i
            else:
                print( "Please note that value input MUST BE in range 1000..9999" )
        except ValueError:
            print( "Input must be an integer." )

def lopOffAnyOverFlow( i ):
    iStr = str(i)
    if len(iStr) == 5:
        return int(iStr[1:])
    return i

i = takeInValid4Dig()
print( "You entered", i )
i += 1111
print( "After adding 1111, the number i is:", i )
i = lopOffAnyOverFlow( i )
print( "After loping off any overflow, the number i is:", i )

print() # a blank line #

def takeInValidPosInt():
    while True:
        try:
            i = int(input( "Enter a positive integer: " ))
            if i >= 0:
                return i
            else:
                print( "Please note that value input MUST BE 0 or greater." )
        except ValueError:
            print( "Input must be an integer." )          

i = takeInValidPosInt()
print( "You entered", i )
iStr = str(i)
iLen = len(iStr)
ones = "1"*iLen

i += int(ones)
print( "After adding {}, the number i is: {}".format( ones, i ) )

I thank you Dave for your recommendations, but it must be an integer and I have done something similar in c in the past as you are recommending. I suppose I am having a real hard time with the scheme syntax or other.

b. extend ... to handle input integers with an arbitrary number of digits.

How do you plan to handle very long integers?

Here is some C++ code that may help:

// incrementEachDigit.cpp //  // 2016-10-28 //

// compile with a C++ 11 or better compiler ... //

#include <iostream>
#include <string>
#include <cctype>

using namespace std;

string takeInLine( const string& prompt )
{
    cout << prompt;
    string line;
    getline( cin, line );
    return line;
}

bool isValidPosInt( const string& str )
{
    for( auto ch : str )
    {
        if( !isdigit(ch) ) return false;
    }
    // if reach here, then ...
    if( str.size() > 0 ) return true;
    // else ...
    return false;
}

string takeInValid4Dig()
{
    while( true )
    {
        string iStr = takeInLine( "Enter a 4 digit int between 1000 and 9999: " );
        if( isValidPosInt(iStr) )
        {
            int i = stoi( iStr );
            if( i >= 1000 && i <= 9999 ) return iStr;
            // else ...
            cout << "Only values in range 1000..9999 accepted here.\n";
        }
        else cout << "Only positive integers are accepted here.\n";
    }
}

string& lopOffAny4DigOverFlow( string& str )
{
    if( str.size() == 5 )
        str.erase(0, 1);
    return str;
}

string takeInValidPosInt()
{
    while( true )
    {
        string iStr = takeInLine( "Enter a positive int: " );
        if( isValidPosInt(iStr) )
            return iStr;
        else
            cout << "Only positive integers are accepted here.\n";
    }
}

string& inc( string& str )
{
    int carry = 0, end = str.size()-1, over;
    for( ; end >= 0; -- end )
    {
        str[end] = carry + 1 + str[end];
        if( str[end] > '9' )
        {
            carry = 1;
            over = str[end] - '9';

            if( over == 2 ) str[end] = '1';
            else str[end] = '0';
        }
        else carry = 0;
    }

    if( carry == 1 ) str = '1' + str;

    return str;
}

int main()
{
    string iStr = takeInValid4Dig();
    cout << "You entered " << iStr << endl;
    iStr = inc( iStr );
    cout <<  "After calling inc(iStr) the number iStr is: " << iStr << endl;
    iStr = lopOffAny4DigOverFlow( iStr );
    cout <<  "After loping off any overflow, the number iStr is: " << iStr << endl;

    cout << endl; // print a blank line ... //

    iStr = takeInValidPosInt();
    cout << "You entered " << iStr << endl;
    iStr = inc( iStr );
    cout << "After calling inc(iStr), the number iStr is: " << iStr;

    cout << "\n\nPress 'Enter' to continue/exit ... ";
    cin.get();
}

I think you might need to revise your logic a bit. See if something like this helps:

counter = 0
while input > 0
output = output + ((input mod 10) mod 10) * (counter pow 10)
input = floor(input/10)
count = counter + 1
endloop
return output

If you need some c++ code I could mock that up for you.

Alao, big integers are not necessary because scheme naturally handles infinitely long numbers.

Oops, had a flaw in my logic example:

counter = 0
while input > 0
output = output + (((input mod 10) + 1) mod 10) * (counter pow 10)
input = floor(input/10)
counter = counter + 1
endloop
return output

Not only will this allow any size integer, but will handle the edge case of a 9 rolling over to a 0.

Just fix the rest kkk..

short input = 6699;
short output = 0;
short result = 0;
short div = 1;
for (int counter = 0; counter < 4; ++counter)
{
    if (counter > 0)
        input = input / 10;
    output = input % 10 + 1;
    if (output > 9)
        output = 0;
    result += div * output;
    div *= 10;
}

Here is a short python version

def digitinc(a):
    return int(''.join(str((1 + int(x)) % 10) for x in str(a)))

OK, Scheme language is a bit similar to Lisp but not quite. Thus, you SHOULD think of a solution in recursive. You should never try to solve a problem using iterative function.

The language deals best with list type data, so you should convert your integer to a list. It also provides you both getting the 1st item in the list (car) and the rest of the list (cdr). You will need those functions in your manipulation. In your recursive call, you will need to call another function which take one digit which is taken off from the input number, increase it by 1, and then return the result with moding by 10 (return 0 if 9+1 is 10). The second part is to recursive call the function given the rest of the number list again. And then concatenate your result (con) them all into one number/string.

Hope this would give you some ideas.

Edited: Your first code is already wrong. If an input is 3459, your output would be 4570 instead of 4560.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.