I would like to know if there is any way to count like this:
base of each position:
4 2 3
counter values:
000--invalid - exception, always a non zero digit must be there
001
002
010
011
012
100
101--invalid : disconnected digits
102--invalid : disconnected digits
110
111
112
200
201--invalid : disconnected digits
202--invalid : disconnected digits
210
211
212
300
301--invalid : disconnected digits
302--invalid : disconnected digits
310
311
312
The idea is if non-zero digits are separated by zero, then leave that formation out. That means values like 101, 201 are invalid.
talking about decimal counting system for example (max: 9999), numbers like 1001, or 9010 will not be produced.
I came up with counting and then converting to each base, (in my first example, the bases would be 4.2.3 and for the 9999 example it would be 10.10.10.10) however, there are certain numbers of all numbers that they will be valid.
for example:
4.2.3: 17 out of 4*2*3 (or 24) will be valid
4.2.2.4: 30 out of 4*2*2*4 (or 64) will be valid
10.10.10.10: 8298 out of 10*10*10*10 (or 10000) will be valid.
as positions goes up, the more computation I need to perform.
What is your idea about a fast counter that can produce such numbers?
a simple solution as I mentioned would be count and convert, and then do a post process on generated numbers, but what is the optimized solution for this?
here is my code:
/**
* Author: Soleyman Pasban
* Date: Apr 6, 2016
*/
package PC;
public class DigitTest {
public static void main(String[] test) {
//int[] base = new int[]{4, 2, 3};
int[] base = new int[]{4, 2, 2, 4};
//int[] base = new int[]{10,10,10,10};
int valid = 0;
int total = 1;
for (int i = 0; i < base.length; i++) {
total *= base[i];
}
for (int i = 1; i < total; i++) {
int number = i;
int bi = base.length - 1;
String str = "";
while (bi >= 0) {
str = number % base[bi] + str;
number = number / base[bi];
bi--;
}
boolean pass = true;
boolean allowNonZero = true;
for (int j = 1; j < base.length; j++) {
if (str.charAt(j - 1) == '0' && str.charAt(j) != '0') {
//for the first case ...0* it should filter the cases
//I bypass it once by this, else the number must mark invalid
if (allowNonZero == false) {
pass = false;
}
allowNonZero = false;
}
//once see a zero, no none-zero must be appear
if (str.charAt(j - 1) != '0') {
allowNonZero = false;
}
}
if (pass) {
valid++;
} else {
str += " - invalid";
}
System.out.println(str);
}
System.out.println();
System.out.println("Valid: " + valid);
System.out.println("Total: " + total);
}
}
My question is if there is a way to keep the above algorithm simple. for a 16 digits like 4.8.7.2.2.3.2.2.4.2.7.4.2.3.2.2 (this is an example to show that it must work with any base) the amount of calculation, creating string variables and other stuff I think will be inefficient!
for an example if a number start with like 9010*********1 then this number is wrong from the beginning and counting the rest will be meaningless.
Is there any other solution for this problem? I would like to see if I can just produce the valid numbers by this.
Thanks
It's actually fairly simple. You start by creating a char[] of '0' characters for the appropriate length.
You then increment the last digit, and rollover when necessary. The updated array is then the next value, and you create the result using new String(buf).
Now, the trick is that when you roll over, you set the digit back to 0, and move one position to the left, and increment that. But, you remember how far you had to go left during chained rollovers, because you must increment the left-most zero on the next iteration, in order to prevent "disconnected digits".
Example:
1999
2000 <-- rollover, remember that second digit must be incremented next
2100 <-- now remember that third digit must be incremented next
2110 <-- now remember that forth digit must be incremented next
2111 <-- normal increment
2112 <-- normal increment
Since a weird counter like this is best if reusable, here is a class implementing this logic, including validation:
public final class WeirdCounter {
private int[] bases;
private char[] buf;
private int idx;
public WeirdCounter(int ... bases) {
if (bases.length == 0)
throw new IllegalArgumentException("No bases");
for (int base : bases)
if (base < 1 || base > 10)
throw new IllegalArgumentException("Invalid base:" + base);
this.bases = bases.clone();
this.buf = new char[bases.length];
Arrays.fill(this.buf, '0');
this.idx = this.buf.length - 1;
}
public String next() {
while (this.idx >= 0) {
char digit = this.buf[this.idx];
if (++digit < '0' + this.bases[this.idx]) {
this.buf[this.idx] = digit;
if (this.idx < this.buf.length - 1)
this.idx++;
return new String(this.buf);
}
this.buf[this.idx--] = '0';
}
return null;
}
}
This is very fast and easy to use:
WeirdCounter counter = new WeirdCounter(4,2,3);
for (String val; (val = counter.next()) != null; )
System.out.println(val);
OUTPUT
001
002
010
011
012
100
110
111
112
200
210
211
212
300
310
311
312
Note that the 16-digit example you gave (4.8.7.2.1.3...4.6.7.9.10...3.1.1) makes no sense. What does ... mean? Also, a base of 1 means that the digit can only ever be 0.
So, assuming that . means 1, the code will work. When a rollover crosses any such base-1 value, all digit to the right must stay 0.
Partial output using new WeirdCounter(4,8,7,2,1,3,1,4,6,7,9,10,1,3,1,1):
...
0000000356870000
0000000356880000
0000000356890000
0000010000000000
0000020000000000
0001000000000000
0010000000000000
0011000000000000
0020000000000000
0021000000000000
0030000000000000
0031000000000000
0040000000000000
0041000000000000
0050000000000000
0051000000000000
0060000000000000
0061000000000000
0100000000000000
0110000000000000
0111000000000000
...
Still, code is very, very fast, because when it tries to increment 0001000000000000, it knows to increment the first zero after the 1, so it immediate rolls over the base-1 digit and then increments the 1 digit to 2 instead, without even looking at the those other 0 digits.
public class Digits {
// make constructor or something
int[] base = new int[]{4, 2, 3};
int[] cur = new int[]{0, 0, 0};
public void find(int i, boolean hasNonZero) {
if (i == base.length) {
if (!hasNonZero) {
return; // all zeroes corner case
}
// output
for (int j = 0; j < base.length; j++) {
System.out.print(cur[j]);
}
System.out.println();
return;
}
for (int v = 0; v < base[i]; v++) { // each digit at position
if (hasNonZero && v != 0 && cur[i - 1] == 0) { // disconnected non zeroes
continue;
}
cur[i] = v;
find(i + 1, hasNonZero || v != 0); // next position
}
}
public static void main(String[] args) {
(new Digits()).find(0, false);
}
}
Simple recursion like this.
You can calculate the count without generating any numbers. Here's a simple O(n^3) solution to demonstrate the idea. It can probably be improved further.
public class DigitTest {
public static void main(String[] args) {
countWeirdNumbers(4, 2, 3);
countWeirdNumbers(4, 2, 2, 4);
countWeirdNumbers(10, 10, 10, 10);
}
public static void countWeirdNumbers(int... bases) {
long count = 0;
for (int start = 0; start < bases.length; start++) {
for (int end = start; end < bases.length; end++) {
int thisCount = 1;
for (int i = start; i <= end; i++) {
thisCount *= bases[i] - 1;
}
count += thisCount;
}
}
System.out.println(count);
}
}
The idea is that you're simply counting how many numbers don't have any zeroes in between the first and last nonzero digits. So iterate over all the possible positions of those two digits and count the possibilities for the digits in that range. Each digit has b-1 possibilities where b is the base at that position because 0 isn't allowed.
Here's a super-fast way that doesn't generate any invalid numbers. Just change the initializers for maxdigits and current for different base sequences.
It works by directly incrementing the previous number, so you can make an iterator out of it if you like.
This is good pattern to remember for generating a wide variety of different kinds of sequences in lexical order:
Given the "current item", you can always make the next item with these 2 steps:
Increment the rightmost character that can be greater than the corresponding character in the current item. This works because the next item must be greater, and given that must share the longest possible prefix in common with the current item. Then
Set the remaining characters to the lowest possible value, because otherwise you'd be skipping some.
These steps make it pretty easy to generate your sequence, and indeed a whole lot of other lexically ordered sequences.
public static void main (String[] args) throws java.lang.Exception
{
char[] maxdigits = "312".toCharArray();
char[] current = "001".toCharArray();
for (;;)
{
System.out.println(new String(current));
//each time we add 1, one digit is incremented by one,
//and all the lower-place digits are set to the least possible
//value
//Step 1 - find the position of digit to increment
boolean sawNonZero=false;
int incpos;
for(incpos = current.length-1; incpos>=0; --incpos)
{
if (current[incpos]=='0')
{
if (sawNonZero || current[incpos-1]!='0')
{
//can increment a leading zero or the first trailing zero
break;
}
//incrementing this one would create a zero gap
}
else
{
sawNonZero = true;
if (current[incpos]<maxdigits[incpos])
{
//can increment a digit that is less than max
break;
}
}
}
if (incpos<0)
{
break; //done
}
current[incpos]++;
//Step 2 - set the remaining digits to 0
for (incpos+=1; incpos<current.length; ++incpos)
{
current[incpos]='0';
}
}
}
Related
Came across this question in a Glassdoor review and thought it was interesting.
Given an integer consisting of 4 digits, we need to maximize it in 24
hour format. For example, 4372 should return a String of the form
23:47, which is the maximum 24 hour value that can be obtained from
the given integer. Assume the given integer always contains exactly 4 digits.
Here's an incomplete method I wrote trying to solve it:
private static String maximize24Hour(int digits) {
if (digits == 0)
return "00:00";
if (digits < 0)
return null;
ArrayList<Integer> list = new ArrayList<>();
do {
list.add(digits % 10);
digits /= 10;
} while (digits != 0);
// Extra processing needs to be done here. Haven't figured it out.
StringBuilder buf = new StringBuilder();
for (Integer d : list) {
buf.append(d);
}
String result = buf.toString();
String hours = result.substring(0, 2);
String minutes = result.substring(2, result.length());
if (Integer.parseInt(result) > 2359
|| Integer.parseInt(hours) > 23
|| Integer.parseInt(minutes) > 59
|| result.length() != 4)
return null;
return hours.concat(":").concat(minutes);
}
Am I even approaching it correctly? If this was just any number, it would be trivial. But it's asking for it to be in 24 hour format which is what I find tricky.
I'd be interested to see if anyone has solutions/ideas for this challenge.
Separate the integer into 4 digits.
If you don't have a 0, 1, or 2 then there is no answer.
Put the largest number that is <= 2 in the first spot in the time.
If the first digit was a 2, then put the largest remaining number that is <=3 in the second place. (If there isn't one, then there is no answer.) If the first digit was 1 or 0, then place the largest remaining number in the second place.
Put the largest remaining number that is <= 5 in the third place.
Put the only remaining number in the fourth place.
I think you don't need to back-track at any point because the bounds in steps 3, 4, and 5 are strictly increasing. You certainly don't need to consider all possible permutations of the numbers since we know that certain places are bounded.
Here is my method. May not be the most efficient one, but it does the job.
Break input into individual digits
Get all permutations of all digits
Check each output is valid, and keep track of the biggest.
High level looks like this:
import java.util.List;
import java.util.ArrayList;
public class MaxDigit {
// ... helper functions here
// maximize function
private static String maximize24Hour(int digits) {
if (digits < 1000 || digits >= 10000) {
return "invalid input";
}
// get all possibles and find the biggest
int max = -1;
List<String> singleDigits = getDigits(digits);
List<String> allPossibles = getPermutations(singleDigits);
for (String timeStr : allPossibles) {
int timeInt = Integer.parseInt(timeStr);
if (isValidTime(timeInt) && timeInt > max) {
max = timeInt;
}
}
// If none is valid
if (max < 0) {
return "cannot find any valid time";
}
// Convert int to time
return max/100 + ":" + max%100;
}
public static void main(String[] args) {
System.out.println(maximize24Hour(4372));
}
}
And here are the helpers:
/**
* Check specified time is valid
* #param time Time in hhmm format
* #return true if input time is valid
*/
private static boolean isValidTime(int time) {
int hour = time / 100;
int min = time % 100;
return hour <= 23 && min <= 59;
}
/**
* Generate all possible numbers from input
*
* For example: inputs {1, 2} gives {12, 21}
* For example: inputs {1, 2, 3} gives {123, 132, 213, 231, 312, 321}
*
* #param inputs Input digits
* #return all possibles
*/
private static List<String> getPermutations(List<String> inputs) {
if (inputs.size() <= 1) {
return inputs;
}
List<String> ret = new ArrayList<>();
for (int i = 0; i < inputs.size(); ++i) {
List<String> copy = new ArrayList<>(inputs);
copy.remove(i);
List<String> recusive = getPermutations(copy);
for (String values : recusive) {
ret.add(inputs.get(i) + values);
}
}
return ret;
}
private static List<String> getDigits(int digits) {
List<String> singleDigits = new ArrayList<>();
while (digits > 0) {
singleDigits.add(Integer.toString(digits%10));
digits /= 10;
}
return singleDigits;
}
Suppose I have a number 123. I need to see if I get all digits 1 through 9, including 0. The number 123 has three digits: 1,2, and 3. Then I multiply it by 2 and get 246 (I get digits 2, 4, 6). Then I multiply it by 3 and I get 369. I keep doing incremental multiplication until I get all digits.
My approach is the following:
public int digitProcessSystem(int N) {
String number = Integer.toString(N);
String [] arr = number.split("");
// List <Integer> arr2 = new ArrayList<>();
for (Integer i = 0; i < arr.length; i++) {
try {
arr2[i] = Integer.parseInt(arr[i]);
} catch (NumberFormatException e) {
}
}
count =0;
boolean contains = IntStream.of(arr2).anyMatch(x -> x == 1|| x==2 ||x == 3|| x==4|| x == 5|| x==6 ||x == 7|| x==8||x == 9|| x==0);
}
I really don't know how can I keep doing the boolean for digits that did not match in the first trail above because I will definitely get any one of the all digits in the above boolean search. How can I get that if some specific digits are present and some are not so that I can multiply the actual number to do the search for the digits that were not found in the first trial; just like the way I defined in the beginning.
You could wrap that into a while loop and include the numbers into a Set. Once the set has the size 10 all digits are present in the number. I´d also suggest to use a long instead of an int or you´ll be getting wrong results or run into an excpetion. Here´s some example code for this:
private static long digitProcessSystem(long N) {
long numberN = N;
String number = Long.toString(N);
// calculate 10 digits number here yet
if (number.length() < 10) {
// using the smallest possible number with each digit
// By using this number we are most likely allmost at the result
// This will increase the performance for small digits heavily.
long divider = 1023456789L / numberN;
numberN *= divider;
}
number = Long.toString(numberN);
String[] arr = number.split("");
Set<String> input = new HashSet<>(Arrays.asList(arr));
while(input.size() != 10){
// add N to number
numberN += N;
// Parse the new number
number = Long.toString(numberN);
// split
arr = number.split("");
// clear set
input.clear();
// Add the new numbers to the set. If it has the size 10 now the loop will stop and return the number.
input.addAll(Arrays.asList(arr));
};
return numberN;
}
public static void main(String[] args) {
System.out.println(digitProcessSystem(123));
}
output:
1023458769
I'm not sure what is your end goal. But you can use a HashSet and do something like this in order to achieve what you are trying to achieve:
public static void main (String[] args) throws Exception {
long number = 123L, counter = 1000000000L / number;
while(digitProcessSystem(number * counter++));
System.out.println("Number: " + number * (counter - 1));
}
public static boolean digitProcessSystem(long input) {
char[] arr = Long.toString(input).toCharArray();
Set<Character> set = new HashSet<>();
for (int i = 0; i < arr.length; i++) {
set.add(arr[i]);
}
return set.size() != 10;
}
Output:
Number: 1023458769
without using java language Facilities and hashset:
private static long digitProcessSystem(long N) {
long numberN = N;
String number = Long.toString(N);
String[] arr = number.split("");;
int arr2=new int[10];
int sum=0;
while(sum != 10){
sum=0;
// add N to number
numberN += N;
// Parse the new number
number = Long.toString(numberN);
// If it doesn´t have 10 digitis continue here yet
if(number.length() < 10) continue;
// split
arr = number.split("");
for(int i=0;i<arr.length;i++){
arr2[arr]=1;
}
for(int i=0;i<10;i++){
sum+=arr2[i];
}
};
return numberN;
}
Generally, if you want to process the characters of a String, don’t do it by splitting the string into substrings. Note that every CharSequence, including String, has the methods chars() and codepoints() allowing to process all characters as IntStream.
To check whether all digits from '0' to '9' are present, we can use chars() (don’t have to think about surrogate pairs) and do it straight-forward, map them to their actual number by subtracting '0', filter out all non-digits (just to be sure), then, map them to an int where the nth bit is set, so we can binary or them all together and check whether all of the lowest ten bits are set:
public static boolean hasAllDigits(String s) {
return s.length()>9 &&
s.chars().map(c -> c-'0').filter(c -> c>=0 && c<=9)
.map(c -> 1 << c).reduce(0, (a,b)->a|b) == 0b1111111111;
}
As a bonus, a length-check is prepended as a String must have at least ten characters to contain all ten digits, so we can short-cut if it hasn’t.
Now, I’m not sure about your actual task. If you just want to iterate until encountering a number having all digits, it’s quite simple:
long number=123;
for(long l = 1, end = Long.MAX_VALUE/number; l < end; l++) {
long candidate = number * l;
if(hasAllDigits(String.valueOf(candidate))) {
System.out.println("found: "+candidate);
return;
}
}
System.out.println("not found within the long range");
But if you want to know when you encountered all digits within the sequence of numbers, we have to adapt the test method and keep the bitset between the iterations:
public static int getDigits(String s) {
return s.chars().map(c -> c-'0').filter(c -> c>=0 && c<=9)
.map(c -> 1 << c).reduce(0, (a,b)->a|b);
}
long number=123;
int digits=0;
for(long l = 1, end = Long.MAX_VALUE/number; l < end; l++) {
long candidate=number * l;
int newDigits=digits | getDigits(String.valueOf(candidate));
if(newDigits != digits) {
System.out.printf("pos %10d: %10d%n", l, candidate);
digits=newDigits;
if(digits == 0b1111111111) {
System.out.println("encountered all digits");
break;
}
}
}
if(digits != 0b1111111111) {
System.out.println("did not encounter all digits within the long range");
}
This method will only print numbers of the sequence which have at least one digit not encountered before, so you can easily see which one contributed to the complete set and will see at most ten numbers of the sequence.
At a recent computer programming competition that I was at, there was a problem where you have to determine if a number N, for 1<=N<=1000, is a palindromic square. A palindromic square is number that can be read the same forwards and backwards and can be expressed as the sum of two or more consecutive perfect squares. For example, 595 is a palindrome and can be expressed as 6^2 + 7^2 + 8^2 + 9^2 + 10^2 + 11^2 + 12^2.
I understand how to determine if the number is a palindrome, but I'm having trouble trying to figure out if it can be expressed as the sum of two or more consecutive squares.
Here is the algorithm that I tried:
public static boolean isSumOfSquares(int num) {
int sum = 0;
int lowerBound = 1;
//largest square root that is less than num
int upperBound = (int)Math.floor(Math.sqrt(num));
while(lowerBound != upperBound) {
for(int x=lowerBound; x<upperBound; x++) {
sum += x*x;
}
if(sum != num) {
lowerBound++;
}
else {
return true;
}
sum=0;
}
return false;
}
My approach sets the upper boundary to the closest square root to the number and sets the lower bound to 1 and keeps evaluating the sum of squares from the lower bound to the upper bound. The issue is that only the lower bound changes while the upper bound stays the same.
This should be an efficient algorithm for determining if it's a sum of squares of consecutive numbers.
Start with a lower bound and upper bound of 1. The current sum of squares is 1.
public static boolean isSumOfSquares(int num) {
int sum = 1;
int lowerBound = 1;
int upperBound = 1;
The maximum possible upper bound is the maximum number whose square is less than or equal to the number to test.
int max = (int) Math.floor(Math.sqrt(num));
While loop. If the sum of squares is too little, then add the next square, incrementing upperBound. If the sum of squares is too high, then subtract the first square, incrementing lowerBound. Exit if the number is found. If it can't be expressed as the sum of squares of consecutive numbers, then eventually upperBound will exceed the max, and false is returned.
while(sum != num)
{
if (sum < num)
{
upperBound++;
sum += upperBound * upperBound;
}
else if (sum > num)
{
sum -= lowerBound * lowerBound;
lowerBound++;
}
if (upperBound > max)
return false;
}
return true;
Tests for 5, 11, 13, 54, 181, and 595. Yes, some of them aren't palindromes, but I'm just testing the sum of squares of consecutive numbers part.
1: true
2: false
3: false
4: true
5: true
11: false
13: true
54: true
180: false
181: true
595: true
596: false
Just for play, I created a Javascript function that gets all of the palindromic squares between a min and max value: http://jsfiddle.net/n5uby1wd/2/
HTML
<button text="click me" onclick="findPalindromicSquares()">Click Me</button>
<div id="test"></div>
JS
function isPalindrome(val) {
return ((val+"") == (val+"").split("").reverse().join(""));
}
function findPalindromicSquares() {
var max = 1000;
var min = 1;
var list = [];
var done = false,
first = true,
sum = 0,
maxsqrt = Math.floor(Math.sqrt(max)),
sumlist = [];
for(var i = min; i <= max; i++) {
if (isPalindrome(i)) {
done = false;
//Start walking up the number list
for (var j = 1; j <= maxsqrt; j++) {
first = true;
sum = 0;
sumlist = [];
for(var k = j; k <= maxsqrt; k++) {
sumlist.push(k);
sum = sum + (k * k);
if (!first && sum == i) {
list.push({"Value":i,"Sums":sumlist});
done = true;
}
else if (!first && sum > i) {
break;
}
first = false;
if (done) break;
}
if (done) break;
}
}
}
//write the list
var html = "";
for(var l = 0; l < list.length; l++) {
html += JSON.stringify(list[l]) + "<br>";
}
document.getElementById("test").innerHTML = html;
}
Where min=1 and max=1000, returns:
{"Value":5,"Sums":[1,2]}
{"Value":55,"Sums":[1,2,3,4,5]}
{"Value":77,"Sums":[4,5,6]}
{"Value":181,"Sums":[9,10]}
{"Value":313,"Sums":[12,13]}
{"Value":434,"Sums":[11,12,13]}
{"Value":505,"Sums":[2,3,4,5,6,7,8,9,10,11]}
{"Value":545,"Sums":[16,17]}
{"Value":595,"Sums":[6,7,8,9,10,11,12]}
{"Value":636,"Sums":[4,5,6,7,8,9,10,11,12]}
{"Value":818,"Sums":[2,3,4,5,6,7,8,9,10,11,12,13]}
An updated version which allows testing individual values: http://jsfiddle.net/n5uby1wd/3/
It only took a few seconds to find them all between 1 and 1,000,000.
You are looking for S(n, k) = n^2 + (n + 1)^2 + (n + 2)^2 + ... (n + (k - 1))^2 which adds up to a specified sum m, i.e., S(n, k) = m. (I'm assuming you'll test for palindromes separately.) S(n, k) - m is a quadratic in n. You can easily work out an explicit expression for S(n, k) - m, so solve it using the quadratic formula. If S(n, k) - m has a positive integer root, keep that root; it gives a solution to your problem.
I'm assuming you can easily test whether a quadratic has a positive integer root. The hard part is probably determining whether the discriminant has an integer square root; I'm guessing you can figure that out.
You'll have to look for k = 2, 3, 4, .... You can stop when 1 + 4 + 9 + ... + k^2 > m. You can probably work out an explicit expression for that.
since there are only few integer powers, you can create an array of powers.
Then you can have 1st and last included index. Initially they are both 1.
while sum is lower than your number, increase last included index. Update sum
while sum is higher, increase 1st included index. Update sum
Or without any array, as in rgettman's answer
Start with an array of The first perfect squares, Let's say your numbers are 13 and 17 , then your array will contain: 1, 4, 9, and 16
Do this kind of checking:
13 minus 1 (0^2) is 12. 1 is a perfect square, 12 is not.
13 minus 2(1^2) is 11. 2 is a perfect square, 11 is not.
13 minus 4(2^2) is 9. 4 is a perfect square, 9 is a perfect square, so 13 is the sum of two perfect
17 minus 1 is 16. 1 and 16 are perfect squares. Eliminate choice.
Keep going until you find one that is not the sum of two perfect squares or not.
One method (probably not efficient) I can think of off the top of my head is,
Suppose N is 90.
X=9 (integer value of sqrt of 90)
1. Create an array of all the integer powers less than x [1,4,9,16,25,36,49,64,81]
2. Generate all possible combinations of the items in the array using recursion. [1,4],[1,9],[1,16],....[4,1],[4,9],....[1,4,9]....3. For each combination (as you generate)- check if the sum of add up to N
**To save memory space, upon generating each instance, you can verify if it sums up to N. If not, discard it and move on to the next.
One of the instances will be [9,81] where 9+81=[90]
I think you can determine whether a number is a sum of consecutive squares quickly in the following manner, which vastly reduces the amount of arithmetic that needs to be done. First, precompute all the sums of squares and place them in an array:
0, 0+1=1, 1+4=5, 5+9=14, 14+16=30, 30+25=55, 55+36=91, ...
Now, if a number is the sum of two or more consecutive squares, we can complete it by adding a number from the above sequence to obtain another number in the above sequence. For example, 77=16+25+36, and we can complete it by adding the listed number 14=0+1+4+9 to obtain the listed number 91=14+77=(0+1+4+9)+(16+25+36). The converse holds as well, provided the two listed numbers are at least two positions apart on the list.
How long does our list have to be? We can stop when we add the first square of n which satisfies (n-1)^2+n^2 > max where max in this case is 1000. Simplifying, we can stop when 2(n-1)^2 > max or n > sqrt(max/2) + 1. So for max=1000, we can stop when n=24.
To quickly test membership in the set, we should hash the numbers in the list as well as storing them in the list; the value of the hash should be the location of the number in the list so that we can quickly locate its position to determine whether it is at least two positions away from the starting point.
Here's my suggestion in Java:
import java.util.HashMap;
public class SumOfConsecutiveSquares {
// UPPER_BOUND is the largest N we are testing;
static final int UPPER_BOUND = 1000;
// UPPER_BOUND/2, sqrt, then round up, then add 1 give MAX_INDEX
static final int MAX_INDEX = (int)(Math.sqrt(UPPER_BOUND/2.0)) + 1 + 1;
static int[] sumsOfSquares = new int[MAX_INDEX+1];
static HashMap<Integer,Integer> sumsOfSquaresHash
= new HashMap<Integer,Integer>();
// pre-compute our list
static {
sumsOfSquares[0] = 0;
sumsOfSquaresHash.put(0,0);
for (int i = 1; i <= MAX_INDEX; ++i) {
sumsOfSquares[i] = sumsOfSquares[i-1] + i*i;
sumsOfSquaresHash.put(sumsOfSquares[i],i);
}
}
public static boolean isSumOfConsecutiveSquares(int N) {
for (int i=0; i <= MAX_INDEX; ++i) {
int candidate = sumsOfSquares[i] + N;
if (sumsOfSquaresHash.containsKey(candidate)
&& sumsOfSquaresHash.get(candidate) - i >= 2) {
return true;
}
}
return false;
}
public static void main(String[] args) {
for (int i=0; i < 1000; ++i) {
if (isSumOfConsecutiveSquares(i)) {
System.out.println(i);
}
}
}
}
Each run of the function performs at most 25 additions and 25 hash table lookups. No multiplications.
To use it efficiently to solve the problem, construct 1, 2, and 3-digit palindromes (1-digit are easy: 1, 2, ..., 9; 2-digit by multiplying by 11: 11, 22, 33, ..., 99; 3-digit by the formula i*101 + j*10. Then check the palindromes with the function above and print out if it returns true.
public static boolean isSumOfSquares(int num) {
int sum = 0;
int lowerBound = 1;
//largest square root that is less than num
int upperBound = (int)Math.floor(Math.sqrt(num));
while(lowerBound != upperBound) {
sum = 0
for(int x=lowerBound; x<upperBound; x++) {
sum += x * x;
}
if(sum != num) {
lowerBound++;
}
else {
return true;
}
}
return false;
}
Perhaps I am missing the point, but considering N, for 1<=N<=1000 the most efficient way would be to solve the problem some way (perhaps brute force) and store the solutions in a switch.
switch(n){
case 5:
case 13:
...
return true;
default:
return false;
}
public static boolean validNumber(int num) {
if (!isPalindrome(num))
return false;
int i = 1, j = 2, sum = 1*1 + 2*2;
while (i < j)
if (sum > num) {
sum = sum - i*i; i = i + 1;
} else if (sum < num) {
j = j + 1; sum = sum + j*j;
} else {
return true;
}
return false;
}
However There Are Only Eleven "Good Numbers" { 5, 55, 77, 181, 313, 434, 505, 545, 595, 636, 818 }. And This Grows Very Slow, For N = 10^6, There Are Only 59.
The following is the problem I'm working on and my snippet of code.
Is there a better way to implement this? I have used basic control structures for this below.
Is it better to store the rows and columns in a map and searching through the map based on the key/value pairs?
There is a security keypad at the entrance of a building. It has 9 numbers 1 - 9 in a 3x3 matrix format.
1 2 3
4 5 6
7 8 9
The security has decided to allow one digit error for a person but that digit should be horizontal or vertical. Example: for 5 the user is allowed to enter 2, 4, 6, 8 or for 4 the user is allowed to enter 1, 5, 7. IF the security code to enter is 1478 and if the user enters 1178 he should be allowed.
The following is a snippet of code i was working on:
ArrayList<Integer> list = new ArrayList<Integer>();
int num = 9;
int[][] arr = {{1,2,3},{4,5,6},{7,8,9}};
for(int i =0;i< arr.length;i++){
for(int j = 0; j <arr.length;j++){
if(num == arr[i][j]){
row = i;
col = j;
break;
}
}
}
for(int j1 = 0; j1< 3 ; j1++){
if(arr[row][j1] != num){
list.add(arr[row][j1]);
}
}
for(int i1 = 0 ; i1 <3;i1++){
if(arr[i1][col] != num){
list.add(arr[i1][col]);
}
}
There are many ways to solve this, but I think it can be solved with HashMaps and HashSets more efficiently than doing several iterations.
If I were you, I would build the data model first using a hash map and a hash set. This is because hash map and hash set have fast lookup, (no iterations)
HashMap<Integer,HashSet<Integer>> values = new HashMap<Integer, HashSet<Integer>>();
//now put in the accepted values for one
HashSet<Integer> oneValues = new HashSet<Integer>();
oneValues.put(1);
oneValues.put(2);
oneValues.put(4);
values.put(1, oneValues);
//put in 2 values
......
Then when you parse your input, if you want to see if an inputed value is accepted for what the code is, just do something like
private boolean isAccepted(int input, int combinationValue)
{
// check to see if the inputed value in the accepted values set
return values.get(combinationValue).contains(input);
}
I would tend to want a function along the lines of isCloseTo(int a, int b) So, say, if I called isCloseTo(5, 5) it would return true. If I called isCloseTo(2, 5) it should return true, too. But if I called isCloseTo(1, 3) it would return false.
So I'd write tests like that:
assertTrue(isCloseTo(5, 5));
OK, that's really easy to get to pass:
public boolean isCloseTo(int a, int b) {return true;}
Then, maybe
assertFalse(isCloseTo(1, 3));
which fails with the above implementation, so I'd need to change it
public boolean isCloseTo(int a, int b) {return a == b;}
That's still an incomplete implementation, so we need another test
assertTrue(isCloseTo(1, 2));
Now we start to need some real substance. And I think I'll leave the rest as an exercise for the reader. Yes, I've left the tricky bits out, but this is a strategy (test-driven design) that leads you more directly to solutions than just trying to write the code. As long as you keep all the test passing, you make steady progress toward a complete solution. Good luck!
There are many different acceptable solutions here. I suppose it's easier to construct 10x10 matrix of integer to check for the errors (for example errorMatrix). First index then will mean original digit, second index - digit typed by user, and value of arr[i][j] is a number of errors for this digit pair. Initialize it that way:
errorMatrix[i][i] = 0 //no error
errorMatrix[i][j] = 1, where i and j are horizontally or vertically neighboring digits
errorMatrix[i][j] = 2, in other cases.
Then for every digit pair you will get number of errors in O(1). You stated that you will accept only one error, so the value of 2 for unmatched pairs will be enough and you can just sum up the error numbers and compare it to one.
So, how to construct this. Iterate through all of the digit pairs and find the value of error. You should better implement function CheckError that will calculate it for digit pair a and b
if a=b, then errorMatrix is 0;
The digits a and b are vertical
neighbors if abs(a-b) = 3. So, is
abs(a-b)==3 set errorMatrix[a][b] =
1;
The digits a and b are horizontal
neighbors if
a. (a-1)/3==(b-1)/3 - here we check that this digits are on the same line.
b. abs(a-b)==1 - here we check that digits are in the neighboring cells.
If (a) and (b) then error value is 1;
In other cases error value is 2.
It seems to me that this spec is right. However, you need to test it before using
So, if you then want to handle the changes of the keypad layout you just have to rewrite CheckError method.
Hope it helps.
Or this...
boolean matchDigit(int p, int d) {
return (p==d)
|| (p==d-3)
|| (p==d+3)
|| (d%3!=1 && p==d-1)
|| (d%3!=0 && p==d+1);
}
this assumes we've already assured that p and d are between 1 and 9.
For the specific keyboard in your question we can use a base 3 to solve this problem and to calculate the distances between digits/keys.
1 { 1 / 3, 1 % 3 } = {0, 1}
2 { 2 / 3, 2 % 3 } = {0, 2}
...
5 { 5 / 3, 5 % 3 } = {1, 2}
...
8 { 8 / 3, 8 % 3 } = {2, 2}
public boolean isValidCode(int code, int expexted) {
while(code > 0)
{
if (!isValidDigit(code % 10, expected % 10))
return false ;
code /= 10 ;
expected /= 10 ;
}
return (code == expected) ;
}
public boolean isValidDigit(int a, int b) {
int dx = (a - b) / 3 ;
int dy = (a - b) % 3 ;
return ((Math.abs(dx) + Math.abs(dy)) == 1)
}
A more generic and robust solution will be to create a Map where you can set what other keys you accept.
Sample: allowing A, Z, P, M, N for A: place a new entry 'A'="AZPMN" in the map, validation checkd if the character is the same or if the type character is in the exceptions string.
private Map acceptedChars = new HashMap() ;
public void loadAcceptedCharacters() {
acceptedChars.put('A', "AZPMN") ;
}
public boolean isValidKeyword(String word, String expected)
{
if (word == null || word.matches("\\s*"))
return false ;
if (word.length() != expected.length())
return false ;
for(int idx = 0; idx < word.length(); idx++)
{
if (!isValidDigit(word.chatAt(idx), expected.charAt(idx)))
return false ;
}
return true ;
}
public boolean isValidDigit(char chr, char expected) {
String accepted ;
if (chr != expected)
{
accepted = acceptedChars.get(chr) ;
if (accepted == null)
return false ;
if (accepted.indexOf(chr) < 0)
return false ;
}
return true ;
}
I have to generate all variations without repetitions made of digits 0 - 9.
Length of them could be from 1 to 10. I really don't know how to solve it, especially how to avoid repetitions.
Example:
length of variations: 4
random variations: 9856, 8753, 1243, 1234 etc. (but not 9985 - contains repetition)
Can you please help me? Or can you give me the code?
The keyword to look for is permutation. There is an abundance of source code freely available that performs them.
As for keeping it repetition free I suggest a simple recursive approach: for each digit you have a choice of taking it into your variation or not, so your recursion counts through the digits and forks into two recursive calls, one in which the digit is included, one in which it is excluded. Then, after you reached the last digit each recursion essentially gives you a (unique, sorted) list of repetition-free digits. You can then create all possible permutations of this list and combine all of those permutations to achieve your final result.
(Same as duffymo said: I won't supply code for that)
Advanced note: the recursion is based on 0/1 (exclusion, inclusion) which can directly be translated to bits, hence, integer numbers. Therefore, in order to get all possible digit combinations without actually performing the recursion itself you could simply use all 10-bit integer numbers and iterate through them. Then interpret the numbers such that a set bit corresponds to including the digit in the list that needs to be permuted.
Here is my Java code. Feel free to ask if you don't understand. The main point here is:
sort again character array. for example: a1 a2 a3 b1 b2 b3 .... (a1 = a2 = a3)
generate permutation and always keep condition: index of a1 < index of a2 < index of a3 ...
import java.util.Arrays;
public class PermutationDup {
public void permutation(String s) {
char[] original = s.toCharArray();
Arrays.sort(original);
char[] clone = new char[s.length()];
boolean[] mark = new boolean[s.length()];
Arrays.fill(mark, false);
permute(original, clone, mark, 0, s.length());
}
private void permute(char[] original, char[] clone, boolean[] mark, int length, int n) {
if (length == n) {
System.out.println(clone);
return;
}
for (int i = 0; i < n; i++) {
if (mark[i] == true) continue;
// dont use this state. to keep order of duplicate character
if (i > 0 && original[i] == original[i-1] && mark[i-1] == false) continue;
mark[i] = true;
clone[length] = original[i];
permute(original, clone, mark, length+1, n);
mark[i] = false;
}
}
public static void main(String[] args) {
PermutationDup p = new PermutationDup();
p.permutation("abcab");
}
}
I have created the following code for generating permutations where ordering is important and with no repetition. It makes use of generics for permuting any type of object:
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class Permutations {
public static <T> Collection<List<T>> generatePermutationsNoRepetition(Set<T> availableNumbers) {
Collection<List<T>> permutations = new HashSet<>();
for (T number : availableNumbers) {
Set<T> numbers = new HashSet<>(availableNumbers);
numbers.remove(number);
if (!numbers.isEmpty()) {
Collection<List<T>> childPermutations = generatePermutationsNoRepetition(numbers);
for (List<T> childPermutation : childPermutations) {
List<T> permutation = new ArrayList<>();
permutation.add(number);
permutation.addAll(childPermutation);
permutations.add(permutation);
}
} else {
List<T> permutation = new ArrayList<>();
permutation.add(number);
permutations.add(permutation);
}
}
return permutations;
}
}
Imagine you had a magical function - given an array of digits, it will return you the correct permutations.
How can you use that function to produce a new list of permutations with just one extra digit?
e.g.,
if i gave you a function called permute_three(char[3] digits), and i tell you that it only works for digits 0, 1, 2, how can you write a function that can permute 0, 1, 2, 3, using the given permute_three function?
...
once you solved that, what do you notice? can you generalize it?
using Dollar it is simple:
#Test
public void generatePermutations() {
// digits is the string "0123456789"
String digits = $('0', '9').join();
// then generate 10 permutations
for (int i : $(10)) {
// shuffle, the cut (0, 4) in order to get a 4-char permutation
System.out.println($(digits).shuffle().slice(4));
}
}
The code for this is similar to the one without duplicates, with the addition of an if-else statement.Check this code
In the above code,Edit the for loop as follows
for (j = i; j <= n; j++)
{
if(a[i]!=a[j] && !is_duplicate(a,i,j))
{
swap((a+i), (a+j));
permute(a, i+1, n);
swap((a+i), (a+j));
}
else if(i!=j) {} // if no duplicate is present , do nothing
else permute(a,i+1,n); // skip the ith character
}
bool is_duplicate(int *a,int i,int j)
{
if a[i] is present between a[j]...a[i]
return 1;
otherwise
return 0;
}
worked for me
Permutation without repetition is based on theorem, that amount of results is factorial of count of elements (in this case numbers). In your case 10! is 10*9*8*7*6*5*4*3*2*1 = 3628800. The proof why it is exactly right is right solution for generation also.
Well so how. On first position i.e. from left you can have 10 numbers, on the second position you can have only 9 numbers, because one number is on the position on the left and we cannot repeat the same number etc. (the proof is done by mathematical induction).
So how to generate first ten results? According my knowledges, he simplest way is to use cyclic shift. It means the order of number shift to the left on one position (or right if you want) and the number which overflow to put on the empty place.
It means for first ten results:
10 9 8 7 6 5 4 3 2 1
9 8 7 6 5 4 3 2 1 10
8 7 6 5 4 3 2 1 10 9
7 6 5 4 3 2 1 10 9 8
6 5 4 3 2 1 10 9 8 7
5 4 3 2 1 10 9 8 7 6
...
The first line is basic sample, so it is the good idea to put it into set before generation. Advantage is, that in the next step you will have to solve the same problem to avoid undesirable duplicities.
In next step recursively rotate only 10-1 numbers 10-1 times etc.
It means for first 9 results in step two:
10 9 8 7 6 5 4 3 2 1
10 8 7 6 5 4 3 2 1 9
10 7 6 5 4 3 2 1 9 8
10 6 5 4 3 2 1 9 8 7
10 5 4 3 2 1 9 8 7 6
...
etc, notice, that first line is present from previous step, so it must not be added to generated set again.
Algorithm recursively doing exactly that, what is explained above. It is possible to generate all the 3628800 combinations for 10!, because number of nesting is the same as number of elements in array (it means in your case for 10 numbers it lingers about 5min. on my computer) and you need have enough memory if you want to keep all combinations in array.
There is solution.
package permutation;
/** Class for generation amount of combinations (factorial)
* !!! this is generate proper permutations without repeating and proper amount (počet) of rows !!!
*
* #author hariprasad
*/
public class TestForPermutationII {
private static final String BUMPER = "*";
private static int counter = 0;
private static int sumsum = 0;
// definitoin of array for generation
//int[] testsimple = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int[] testsimple = {1, 2, 3, 4, 5};
private int ELEMNUM = testsimple.length;
int[][] shuff;
private String gaps(int len) {
String addGap = "";
for(int i=0; i <len; i++)
addGap += " ";
return addGap;
}
/** Factorial computing */
private int fact(int num) {
if (num > 1) {
return num * fact(num - 1);
} else {
return 1;
}
}
/** Cyclic shift position to the left */
private int[] lShiftPos(int[] arr, int pos) {
int[] work = new int[ELEMNUM];
int offset = -1;
for (int jj = 0; jj < arr.length; jj++) {
if (jj < pos) {
work[jj] = arr[jj];
} else if (jj <= arr.length - 1) {
if (jj == pos) {
offset = arr[pos]; // last element
}
if (jj != (arr.length - 1)) {
work[jj] = arr[jj + 1];
} else {
work[jj] = offset;
}
}
}
return work;
}
private String printBuff(int[] buffer) {
String res = "";
for (int i= 0; i < buffer.length; i++) {
if (i == 0)
res += buffer[i];
else
res += ", " + buffer[i];
}
return res;
};
/** Recursive generator for arbitrary length of array */
private String permutationGenerator(int pos, int level) {
String ret = BUMPER;
int templen = counter;
int[] work = new int[ELEMNUM];
int locsumread = 0;
int locsumnew = 0;
//System.out.println("\nCalled level: " + level);
for (int i = 0; i <= templen; i++) {
work = shuff[i];
sumsum++;
locsumread++;
for (int ii = 0; ii < pos; ii++) {
counter++;
sumsum++;
locsumnew++;
work = lShiftPos(work, level); // deep copy
shuff[counter] = work;
}
}
System.out.println("locsumread, locsumnew: " + locsumread + ", " + locsumnew);
// if level == ELEMNUM-2, it means no another shift
if (level < ELEMNUM-2) {
ret = permutationGenerator(pos-1, level+1);
ret = "Level " + level + " end.";
//System.out.println(ret);
}
return ret;
}
public static void main(String[] argv) {
TestForPermutationII test = new TestForPermutationII();
counter = 0;
int len = test.testsimple.length;
int[] work = new int[len];
test.shuff = new int[test.fact(len)][];
//initial
test.shuff[counter] = test.testsimple;
work = test.testsimple; // shalow copy
test.shuff = new int[test.fact(len)][];
counter = 0;
test.shuff[counter] = test.testsimple;
test.permutationGenerator(len-1, 0);
for (int i = 0; i <= counter; i++) {
System.out.println(test.printBuff(test.shuff[i]));
}
System.out.println("Counter, cycles: " + counter + ", " + sumsum);
}
}
Intensity (number of cycles) of algorithm is sum of incomplete factorials of number of members. So there is overhang when partial set is again read to generate next subset, so intensity is:
n! + n!/2! + n!/3! + ... + n!/(n-2)! + n!(n-1)!
There is one solution which is not from mine, but it is very nice and sophisticated.
package permutations;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* #author Vladimir Hajek
*
*/
public class PermutationSimple {
private static final int MAX_NUMBER = 3;
Set<String> results = new HashSet<>(0);
/**
*
*/
public PermutationSimple() {
// TODO Auto-generated constructor stub
}
/**
* #param availableNumbers
* #return
*/
public static List<String> generatePermutations(Set<Integer> availableNumbers) {
List<String> permutations = new LinkedList<>();
for (Integer number : availableNumbers) {
Set<Integer> numbers = new HashSet<>(availableNumbers);
numbers.remove(number);
if (!numbers.isEmpty()) {
List<String> childPermutations = generatePermutations(numbers);
for (String childPermutation : childPermutations) {
String permutation = number + childPermutation;
permutations.add(permutation);
}
} else {
permutations.add(number.toString());
}
}
return permutations;
}
/**
* #param args
*/
public static void main(String[] args) {
Set<Integer> availableNumbers = new HashSet<>(0);
for (int i = 1; i <= MAX_NUMBER; i++) {
availableNumbers.add(i);
}
List<String> permutations = generatePermutations(availableNumbers);
for (String permutation : permutations) {
System.out.println(permutation);
}
}
}
I think, this is the excellent solution.
Brief helpful permutation indexing Knowledge
Create a method that generates the correct permutation, given an index value between {0 and N! -1} for "zero indexed" or {1 and N!} for "one indexed".
Create a second method containing a "for loop" where the lower bound is 1 and the upper bound is N!. eg.. "for (i; i <= N!; i++)" for every instance of the loop call the first method, passing i as the argument.
def find(alphabet, alpha_current, str, str_current, max_length, acc):
if (str_current == max_length):
acc.append(''.join(str))
return
for i in range(alpha_current, len(alphabet)):
str[str_current] = alphabet[i]
alphabet[i], alphabet[alpha_current] = alphabet[alpha_current], alphabet[i]
find(alphabet, alpha_current+1, str, str_current+1, max_length, acc)
alphabet[i], alphabet[alpha_current] = alphabet[alpha_current], alphabet[i]
return
max_length = 4
str = [' ' for i in range(max_length)]
acc = list()
find(list('absdef'), 0, str, 0, max_length, acc)
for i in range(len(acc)):
print(acc[i])
print(len(acc))