Why aren't 10 and 100 considered Kaprekar numbers? - c#

I'm trying to do the Modified Kaprekar Numbers problem (https://www.hackerrank.com/challenges/kaprekar-numbers) which describes a Kaprekar number by
Here's an explanation from Wikipedia about the ORIGINAL Kaprekar
Number (spot the difference!): In mathematics, a Kaprekar number for a
given base is a non-negative integer, the representation of whose
square in that base can be split into two parts that add up to the
original number again. For instance, 45 is a Kaprekar number, because
45² = 2025 and 20+25 = 45.
and what I don't understand is why 10 and 100 aren't Kaprekar numbers.
10^2 = 1000 and 10 + 00 = 10
Right?
So my solution
// Returns the number represented by the digits
// in the range arr[i], arr[i + 1], ..., arr[j - 1].
// If there are no elements in range, return 0.
static int NumberInRange(int[] arr, int i, int j)
{
int result = 0;
for(; i < j; ++i)
{
result *= 10;
result += arr[i];
}
return result;
}
// Returns true or false depending on whether k
// is a Kaprekar number.
// Example: IsKaprekar(45) = true because 45^2=2025 and 20+25=45
// Example: IsKaprekar(9) = false because the set of the split
// digits of 7^2=49 are {49,0},{4,9} and
// neither of 49+0 or 4+9 equal 7.
static bool IsKaprekar(int k)
{
int square = k * k;
int[] digits = square.ToString().Select(c => (int)Char.GetNumericValue(c)).ToArray();
for(int i = 0; i < digits.Length; ++i)
{
int right = NumberInRange(digits, 0, i);
int left = NumberInRange(digits, i, digits.Length);
if((right + left) == k)
return true;
}
return false;
}
is saying all the Kaprekar numbers between 1 and 100 are
1 9 10 45 55 99 100
whereas the "right" answer is
1 9 45 55 99

In 100+00 the right is 00, which is wrong because in a kaprekar number the right may start with zero (ex: 025) but cannot be entirely 0.
Therefore you can put a condition in the loop that
if(right==0)
return false;

The reason is because 10 x 10 = 100. Then you substring the right part with a length equals d = 2, that is digit count of original value (10), then the left part would be 1.
So l = 1 and r = 00, l + r = 1, that is not equals to 10.
The same for 100. 100 x 100 = 10000. l = 10, r = 000, so l + r = 10 not equal 100.
Here is my solution in JAVA.
static void kaprekarNumbers(int p, int q) {
long[] result = IntStream.rangeClosed(p, q).mapToLong(Long::valueOf)
.filter(v -> {
int d = String.valueOf(v).length();
Long sq = v * v;
String sqSt = sq.toString();
if (sqSt.length() > 1) {
long r = Long.parseLong(sqSt.substring(sqSt.length() - d));
long l = Long.parseLong(sqSt.substring(0, sqSt.length() - d));
return r + l == v;
} else return v == 1;
}).toArray();
if (result.length > 0) {
for (long l : result) {
System.out.print(l + " ");
}
} else {
System.out.println("INVALID RANGE");
}
}

How about something like this.
static bool IsKaprekar(int k)
{
int t;
for (int digits = new String(k).length(); digits > 0; digits--, t *= 10);
long sq = k * k;
long first = sq / t;
long second = sq % t;
return k == first + second;
}
find a number to divide and mod the square with in order to split it. This number should be a factor of 10 based on the number of digits in the original number.
calculate the square.
split the square.
compare the original to the sum of the splits.

Related

Calculating the correct length of string per line with Page X/Y

I got asked a question and now I am kicking myself for not being able to come up with the exact/correct result.
Imagine we have a function that splits a string into multiple lines but each line has to have x number of characters before we "split" to the new line:
private string[] GetPagedMessages(string input, int maxCharsPerLine) { ... }
For each line, we need to incorporate, at the end of the line "x/y" which is basically 1/4, 2/4 etc...
Now, the paging mechanism must also be part of the length restriction per line.
I have been overworked and overthinking and tripping up on things and this seems pretty straight forward but for the life of me, I cannot figure it out! What am I not "getting"?
What am I interested in? The calculation and some part of the logic but mainly the calculation of how many lines are required to split the input based on the max chars per line which also needs to include the x/y.
Remember: we can have more than a single digit for the x/y (i.e: not just 1/4 but also 10/17 or 99/200)
Samples:
input = "This is a long message"
maxCharsPerLine = 10
output:
This i 1/4 // << Max 10 chars
s a lo 2/4 // << Max 10 chars
ng mes 3/4 // << Max 10 chars
sage 4/4 // << Max 10 chars
Overall the logic is simple but its just the calculation that is throwing me off.
The idea: First, find how many digits is the number of lines:
(n = input.Length, maxCharsPerLine = 10)
if n <= 9*(10-4) ==> 1 digit
if n <= 9*(10-5) + 90*(10-6) ==> 2 digits
if n <= 9*(10-6) + 90*(10-7) + 900*(10-8) ==> 3 digits
if n <= 9*(10-7) + 90*(10-8) + 900*(10-9) + 9000*(10-10) ==> No solution
Then, subtract the spare number of lines. The solution:
private static int GetNumberOfLines(string input, int maxCharsPerLine)
{
int n = input.Length;
int x = maxCharsPerLine;
for (int i = 4; i < x; i++)
{
int j, sum = 0, d = 9, numberOfLines = 0;
for (j = i; j <= i + i - 4; j++)
{
if (x - j <= 0)
return -1; // No solution
sum += d * (x - j);
numberOfLines += d;
d *= 10;
}
if (n <= sum)
return numberOfLines - (sum - n) / (x - j + 1);
}
return -2; // Invalid
}
Usage:
private static string[] GetPagedMessages(string input, int maxCharsPerLine)
{
int numberOfLines = GetNumberOfLines(input, maxCharsPerLine);
if (numberOfLines < 0)
return null;
string[] result = new string[numberOfLines];
int spaceLeftForLine = maxCharsPerLine - numberOfLines.ToString().Length - 2; // Remove the chars of " x/y" except the incremental 'x'
int inputPosition = 0;
for (int line = 1; line < numberOfLines; line++)
{
int charsInLine = spaceLeftForLine - line.ToString().Length;
result[line - 1] = input.Substring(inputPosition, charsInLine) + $" {line}/{numberOfLines}";
inputPosition += charsInLine;
}
result[numberOfLines-1] = input.Substring(inputPosition) + $" {numberOfLines}/{numberOfLines}";
return result;
}
A naive approach is to start counting the line lengths minus the "pager"'s size, until the line count changes in size ("1/9" is shorter than "1/10", which is shorter than "11/20", and so on):
private static int[] GetLineLengths(string input, int maxCharsPerLine)
{
/* The "pager" (x/y) is at least 4 characters (including the preceding space) and at most ... 8?
* 7/9 (4)
* 1/10 (5)
* 42/69 (6)
* 3/123 (6)
* 42/420 (7)
* 999/999 (8)
*/
int charsRemaining = input.Length;
var lineLengths = new List<int>();
// Start with " 1/2", (1 + 1 + 2) = 4 length
var highestLineNumberLength = 1;
var lineNumber = 0;
do
{
lineNumber++;
var currentLineNumberLength = lineNumber.ToString().Length; // 1 = 1, 99 = 2, ...
if (currentLineNumberLength > highestLineNumberLength)
{
// Pager size changed, reset
highestLineNumberLength = currentLineNumberLength;
lineLengths.Clear();
lineNumber = 0;
charsRemaining = input.Length;
continue;
}
var pagerSize = currentLineNumberLength + highestLineNumberLength + 2;
var lineLength = maxCharsPerLine - pagerSize;
if (lineLength <= 0)
{
throw new ArgumentException($"Can't split input of size {input.Length} into chunks of size {maxCharsPerLine}");
}
lineLengths.Add(lineLength);
charsRemaining -= lineLength;
}
while (charsRemaining > 0);
return lineLengths.ToArray();
}
Usage:
private static string[] GetPagedMessages(string input, int maxCharsPerLine)
{
if (input.Length <= maxCharsPerLine)
{
// Assumption: no pager required for a message that takes one line
return new[] { input };
}
var lineLengths = GetLineLengths(input, maxCharsPerLine);
var result = new string[lineLengths.Length];
// Cut the input and append the pager
var previousIndex = 0;
for (var i = 0; i < lineLengths.Length; i++)
{
var lineLength = Math.Min(lineLengths[i], input.Length - previousIndex); // To cater for final line being shorter
result[i] = input.Substring(previousIndex, lineLength) + " " + (i + 1) + "/" + lineLengths.Length;
previousIndex += lineLength;
}
return result;
}
Prints, for example:
This 1/20
is a 2/20
long 3/20
strin 4/20
g tha 5/20
t wil 6/20
l spa 7/20
n mor 8/20
e tha 9/20
n te 10/20
n li 11/20
nes 12/20
beca 13/20
use 14/20
of i 15/20
ts e 16/20
norm 17/20
ous 18/20
leng 19/20
th 20/20

Codewar task. How to find simple square numbers by the condition?

I tried to solve this problem on Codewar, but I don`t understand how to find exceptions.
In this Kata, you will be given a number n (n > 0) and your task will be to return the smallest square number N (N > 0) such that n + N is also a perfect square. If there is no answer, return -1 (nil in Clojure, Nothing in Haskell).
Here code that I wrote:
using System;
public class SqNum
{
public static long solve(long n){
int N = 1;
long lTemp = n;
double sum, result;
bool isSqare;
while(true)
{
sum = lTemp + N;
result = Math.Sqrt(sum);
isSqare = result % 1 == 0;
if(n == 4)
{
return -1;
}
if(isSqare == true)
{
return Convert.ToInt32(result);
}
N++;
}
return -1;
}
}
If N (square) is p^2, and n+N=r^2, you can write
n + p^2 = r^2
n = r^2 - p^2
n = (r - p) * (r + p)
If we represent n as product of pair of divisors:
n = a * b // let a<=b
a * b = (r - p) * (r + p)
We have system
r - p = a
r + p = b
and
p = (b - a) / 2
When p is the smallest? In the case of maximal close factors b and a. So we can try to calculate divisors starting from square root of n. Also note that a and b should have the same parity (to make p integer)
Pseudocode:
int N = -1;
for (int a = Math.Ceiling(Math.Sqrt(n)) - 1; a > 0; a--) {
if (n % a == 0) {
int bma = n / a - a;
if (bma % 2 == 0) {
int p = bma / 2;
int N = p * p;
break;
}
}
}
Examples:
n = 16
first divisor below sqrt(16) a = 2, b=8
p = 3, 16 + 9 = 25
n = 13
first divisor below sqrt(13) a = 1, b=13
p = 6, 13 + 36 = 49
n = 72
first divisor below sqrt(72) is a = 8, b= 9 - but distinct parity!
so the next suitable pair is a = 6, b = 12
p = 3, 72 + 9 = 81

Get all n-digit numbers whose sum of digits equals to given sum

How can I get all n-digit numbers whose sum of digits equals to given sum? I need the fastest solution because n can be equal with 9 and sum can be equal with 1000.
I have implemented the solution below but it's too slow...
List<int> l = new List<int>();
void findNDigitNumsUtil(int n, int sum, char[] ou, int index)
{
if (index > n || sum < 0)
return;
if (index == n)
{
if (sum == 0)
{
ou[index] = '\0';
string s = new string(ou);
l.Add(Int32.Parse(s));
}
return;
}
for (int i = 0; i <= 9; i++)
{
ou[index] = (char)(i + '0');
findNDigitNumsUtil(n, sum - i, ou,
index + 1);
}
}
void findNDigitNums(int n, int sum)
{
char[] ou = new char[n + 1];
for (int i = 1; i <= 9; i++)
{
ou[0] = (char)(i + '0');
findNDigitNumsUtil(n, sum - i, ou, 1);
}
}
I need the fastest solution
No, you need a fast-enough solution. You are probably unwilling to spend even a million dollars on custom hardware to get the fastest possible solution.
How can I get all n-digit numbers whose sum of digits equals to given sum?
Here, I'll give you the solution for a slightly different problem:
What are all the sequences of n digits drawn from 0-9 that sum to sum?
This is different because this counts 01 and 10 as sequences of length two that sum to 1, but 01 is not a two-digit number.
I'll give you a hint for how to solve this easier problem. You then take that solution and adapt it to your harder problem.
First, can you solve the problem for one-digit numbers? That's pretty easy. The one-digit numbers whose digits sum to n are the digit n if n is 0 through 9, and there is no solution otherwise.
Second: Suppose n > 1. Then the n-digit numbers that sum to sum are:
0 followed by all the n-1 digit numbers that sum to sum
1 followed by all the n-1 digit numbers that sum to sum-1
2 followed by all the n-1 digit numbers that sum to sum-2
...
9 followed by all the n-1 digit numbers that sum to sum-9
Write an implementation that solves that problem, and then adapt it to solve your problem.
You can treat n-digit number as an array of n digits. Then you can increment a particular number to the next number that also adds up to the sum. Stepping through all the next answers, you have generated all possible combinations.
Using a generator to yield each n-digit combination as an IEnumerable<int> (in fact, an int[]), you start with the "smallest" n-digit combination that yields the sum, and go through each one.
IEnumerable<IEnumerable<int>> DigitsToSum(int n, int sum) {
if (sum > 9 * n)
yield return Enumerable.Empty<int>();
else {
var ans = new int[n];
void distribute(int wsum, int downto) {
for (var j1 = n - 1; j1 > downto; --j1) {
if (wsum > 9) {
ans[j1] = 9;
wsum -= 9;
}
else {
ans[j1] = wsum;
wsum = 0;
}
}
}
ans[0] = Math.Max(1, sum-9*(n-1));
distribute(sum-ans[0], 0);
bool nextAns() {
var wsum = ans[n-1];
for (var j1 = n - 2; j1 >= 0; --j1) {
wsum += ans[j1];
if (ans[j1] < Math.Min(9, wsum)) {
++ans[j1];
distribute(wsum - ans[j1], j1);
return true;
}
}
return false;
}
do {
yield return ans;
} while (nextAns());
}
}
This is tremendously faster than my recursive double generator solution (somewhat like #EricLippert's suggestion) to iterate over all possibilities (e.g. using Count()).
You can put the digits back together to get a final numeric string for each number:
var ans = DigitsToSum(n, sum).Select(p => String.Join("", p));

An algorithm for a number divisible to n

At first user gives a number (n) to program, for example 5.
the program must find the smallest number that can be divided to n (5).
and this number can only consist of digits 0 and 9 not any other digits.
for example if user gives 5 to program.
numbers that can be divided to 5 are:
5, 10, 15, 20, 25, 30, ..., 85, 90, 95, ...
but 90 here is the smallest number that can be divided to 5 and also consist of digits (0 , 9). so answer for 5 must be 90.
and answer for 9 is 9, because it can be divided to 9 and consist of digit (9).
my code
string a = txtNumber.Text;
Int64 x = Convert.ToInt64(a);
Int64 i ,j=1,y=x;
bool t = false;
for (i = x + 1; t == false; i++)
{
if (i % 9 == 0 && i % 10 == 0 && i % x == 0)
{
j = i;
for (; (i /= 10) != 0; )
{
i /= 10;
if (i == 0)
t = true;
continue;
}
}
}
lblAnswer.Text = Convert.ToString(j);
If you're happy to go purely functional then this works:
Func<IEnumerable<long>> generate = () =>
{
Func<long, IEnumerable<long>> extend =
x => new [] { x * 10, x * 10 + 9 };
Func<IEnumerable<long>, IEnumerable<long>> generate2 = null;
generate2 = ns =>
{
var clean = ns.Where(n => n > 0).ToArray();
return clean.Any()
? clean.Concat(generate2(clean.SelectMany(extend)))
: Enumerable.Empty<long>();
};
return generate2(new[] { 9L, });
};
Func<long, long?> f = n =>
generate()
.Where(x => x % n == 0L)
.Cast<long?>()
.FirstOrDefault();
So rather than iterate through all possible values and test for 0 & 9 and divisibility, this just generates only numbers with 0 & 9 and then only tests for visibility. It is much faster this way.
I can call it like this:
var result = f(5L); // 90L
result = f(23L); //990909L
result = f(123L); //99999L
result = f(12321L); //90900999009L
result = f(123212L); //99909990090000900L
result = f(117238L); //990990990099990990L
result = f(1172438L); //null == No answer
These results are super fast. f(117238L) returns a result on my computer in 138ms.
You can try this way :
string a = txtNumber.Text;
Int64 x = Convert.ToInt64(a);
int counter;
for (counter = 1; !isValid(x * counter); counter++)
{
}
lblAnswer.Text = Convert.ToString(counter*x);
code above works by searching multiple of x incrementally until result that satisfy criteria : "consist of only 0 and or 9 digits" found. By searching only multiple of x, it is guaranteed to be divisible by x. So the rest is checking validity of result candidate, in this case using following isValid() function :
private static bool isValid(int number)
{
var lastDigit = number%10;
//last digit is invalid, return false
if (lastDigit != 0 & lastDigit != 9) return false;
//last digit is valid, but there is other digit(s)
if(number/10 >= 1)
{
//check validity of digit(s) before the last
return isValid(number/10);
}
//last digit is valid, and there is no other digit. return true
return true;
}
About strange empty for loop in snippet above, it is just syntactic sugar, to make the code a bit shorter. It is equal to following while loop :
counter = 1;
while(!isValid(input*counter))
{
counter++;
}
Use this simple code
int inputNumber = 5/*Or every other number, you can get this number from input.*/;
int result=1;
for (int i = 1; !IsOk(result,inputNumber); i++)
{
result = i*inputNumber;
}
Print(result);
IsOk method is here:
bool IsOk(int result, int inputNumber)
{
if(result%inputNumber!=0)
return false;
if(result.ToString().Replace("9",string.Empty).Replace("0",string.Empty).Length!=0)
return false;
return true;
}
My first solution has very bad performance, because of converting a number to string and looking for characters '9' and '0'.
New solution:
My new solution has very good performance and is a technical approach since of using Breadth-first search(BFS).
Algorithm of this solution:
For every input number, test 9, if it is answer print it, else add 2 child numbers (90 & 99) to queue, and continue till finding answer.
int inputNumber = 5;/*Or every other number, you can get this number from input.*/
long result;
var q = new Queue<long>();
q.Enqueue(9);
while (true)
{
result = q.Dequeue();
if (result%inputNumber == 0)
{
Print(result);
break;
}
q.Enqueue(result*10);
q.Enqueue(result*10 + 9);
}
Trace of number creation:
9
90,99
900,909,990,999
9000,9009,9090,9099,9900,9909,9990,9999
.
.
.
I wrote this code for console, and i used goto command however it is not prefered but i could not write it with only for.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace main
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter your number");
Int64 x = Convert.ToInt64(Console.ReadLine());
Int64 y, j, i, k, z = x;
x = x + 5;
loop:
x++;
for (i = 0, y = x; y != 0; i++)
y /= 10;
for (j = x, k = i; k != 0; j /= 10, k--)
{
if (j % 10 != 9)
if (j % 10 != 0)
goto loop;
}
if (x % z != 0)
goto loop;
Console.WriteLine("answer:{0}",x);
Console.ReadKey();
}
}
}

How do I determine if adding 2 numbers will involve regourping / carryover or subracting 2 numbers will involve borrowing?

I need to create a function that will generate 2 random numbers between x and y (e.g. x = 1, y = 20) which when added will not involve regrouping / carryover or which when subracted will not involve borrowing.
For example,
18 + 1 = good
14 + 5 = good
18-7 = good
29 - 8 = good
15 + 6 = bad
6 + 7 = bad
21 - 3 = bad
36 - 8 = bad etc.
I want to create a simple worksheet generator that will generate sample problems using the requirements above.
I guess I could always convert the number to string, get the right most digit for each of the 2 numbers, convert them back to integer, and test if one is greater than the other. Repeat for all the digit. Only thing is, that is so damn ugly (read inefficient). I am sure that there is a better way. Anyone have any suggestions? Thanks
Generate them one digit at a time. e.g
a1 = rand(9)
a2 = rand(9 - a1)
b1 = rand(9)
b2 = rand(9 - b1)
x = b1*10 + a1
y = b2*10 + a2
From the construction you know that x+y will not involve any carry, because a1+a2 <= 9 and b1 + b2 <= 9.
You can do similar for subtraction.
If you want to restrict the overall range to be [1..20] instead of [1..99], just adjust the range for the leftmost digit:
b1 = rand(1)
b2 = rand(1 - b1)
using System;
class Sample {
static void Main() {
var rnd = new Random();
var x = 1;
var y = 20;
var a = rnd.Next(x, y);
var b = rnd.Next(x, y);
var op = '+';
Console.WriteLine("{0} {2} {1} = {3}", a, b, op , isValid(a, b, op)? "good":"bad");
op = '-';
Console.WriteLine("{0} {2} {1} = {3}", a, b, op , isValid(a, b, op)? "good":"bad");
}
static bool isValid(int x, int y, char op){
int a = x % 10;
int b = y % 10;
switch (op){
case '+':
return a + b < 10;
case '-':
return x >= y && a - b >= 0;
default:
throw new Exception(String.Format("unknown operator '{0}'", op));
}
}
}
Breaking up the numbers into digits is indeed exactly what you need to do. It does not matter whether you do that by arithmetic manipulation (division and modulus by 10) or by converting the numbers into strings, but fundamentally your question is precisely about the individual digits of the numbers.
For the subtraction x − y, no borrows are required if and only if none of the digits in y are greater than the corresponding digit in x.
For the addition x + y, there will be no carries if and only if the sum of each pair of corresponding digits is less than 10.
Here's some pseudo-C# for checking these conditions:
bool CanSubtractWithoutBorrow (uint x, uint y) {
while (y > 0) {
if ((x % 10) < (y % 10)) return False;
x /= 10; y /= 10;
}
return True;
}
bool CanAddWithoutCarry (uint x, uint y) {
while (x > 0 && y > 0) {
if ((x % 10) + (y % 10) >= 10) return False;
x /= 10; y /= 10;
}
return True;
}
You need to look at each pair digit in turn, and see if adding or subtracting them involves carries.
You can get the rightmost digit by taking the value modulo 10, x%10, and you can erase the right most digit by dividing by 10.
No string conversions are necessary.

Categories

Resources