public class Binar{
public static void main(String[] args){
int num = 7;
long Binary = cBtD(num);
System.out.printf("%d numri decimal = %d binar" , num, Binary);
}
public static long cBtD(int num){
long BinaryNumber = 0;
int i = 0;
long reminder;
while(num > 0){
reminder = num % 2;
num /= 2;
++i;
}
for (int j = i - 1; j >= 0; j--) {
System.out.print(BinaryNumber[j]);
}
return BinaryNumber;
}}
and i have this error and it says "array required, but long found" and "System.out.print(BinaryNumber[j]);"
Reason behind this error is, you have defined BinaryNumber variable as long and it is not an array. But you are trying to access it like an array. Please check my modified answer below:
public class Binar {
public static void main(String[] args) {
int num = 7;
String Binary = cBtD(num);
System.out.printf("%d numri decimal = %s binar", num, Binary);
}
public static String cBtD(int num) {
String BinaryNumber = "";
long reminder;
if (num == 0) {
return "0";
}
while (num > 0) {
reminder = num % 2;
BinaryNumber = String.valueOf(reminder).concat(BinaryNumber);
num /= 2;
}
return BinaryNumber;
}
}
That error occurred because you defined BinaryNumber's type 'long' and you wanted use it as an array.
I change it a bit, try it:
public class Binar {
public static void main(String[] args) {
int num = 7;
int[] binaryArray = cBtD(num);
String numbers = "";
for (int aBinaryArray : binaryArray)
numbers += aBinaryArray;
System.out.printf("%d numri decimal = %d binar" , num, Integer.parseInt(numbers));
}
private static int[] cBtD(int num){
int i = 0;
int temp[] = new int[7];
int binaryNumber[];
while (num > 0) {
temp[i++] = num % 2;
num /= 2;
}
binaryNumber = new int[i];
int k = 0;
for (int j = i - 1; j >= 0; j--) {
binaryNumber[k++] = temp[j];
}
return binaryNumber;
}
}
Or you can simply use these methods to convert decimal to binary:
Integer.toBinaryString();
Or this:
Integer.toString(n,2);
All numbers are inherently binary. But whether you display them in binary or hex or octal is simply a matter of representation. Which means you want to print them as a string. Even when you do the following:
int v = 123;
System.out.println(v); // v is printed as a decimal string.
So to convert them to a binary string, just prepend the remainders to the string after dividing by two (via the remainder operator).
int n = 11;
String s = "";
s = (n%2) + s; // s = "1"
n/=2; // n == 5
s = (n%2) + s; // s = "11"
n/=2 // n == 2
s = (n%2) + s; // s = "011";
n/=2 // n == 1
s = (n%2) + s; // s = "1011";
n/=2; // n == 0
n == 0 so your done.
return s and print it.
I have to write a boolean method that checks if a number n is a circular prime, using only integer computations, so no Strings. I wrote two other methods that have to be included.
boolean isPrime(int n) {
if (n < 1) {
return false;
} else if (n == 1 || n == 2) {
return true;
} else if (n % 2 != 0) {
for (int i = 3; i < n; i+=2) {
if (n % i == 0) {
return false;
}
}
return true;
} else {
return false;
}
}
This checks if the number is a prime.
int largestPowerOfTen(int n) {
for (int i = 1; i < n * 10; i*=10) {
if (n / i == 0) {
return i / 10;
}
}
return 1;
}
This returns the largest power of ten of the number. For instance, 23 would return 10, 704 would return 100, etc.
I had the idea to put every digit into an array and move the digits around from there, but I'm stuck at the moving part.
boolean isCircularPrime(int n) {
ArrayList<Integer> k = new ArrayList<Integer>();
int i = 0;
while (n != 0) {
k.add(n % 10);
n /= 10;
i++;
}
//???
}
So how do I move the digits around?
Assuming a "circular prime number" is a number that is a prime number for all rotations of the digits...
You can't just rotate the number, because zeroes won't be conserved.
First break up the number into an array - each digit of the number an element of the array. Use n % 10 to find the last digit, then n /= 10 until n == 0.
Create a method the generates a number from the array with a specified starting index. This is the crux of the problem, and here's some code:
private static int generate(int[] digits, int index) {
int result = 0;
for (int i = 0; i < digits.length; i++) {
result = result * 10 + digits[(index + i) % digits.length];
}
return result;
}
Then loop over every possible starting index for your digits and check if it's prime.
The remaining code I leave to the reader...
import java.util.Scanner;
class CircularPrime
{
public boolean prime(int n)
{
int lim=n,count=0;
for(int i=1;i<=lim;i++)
{
if(n%i==0)count++;
}
if(count==2)
return true;
else
return false;
}
public int circlize(int n)
{
int len,x,y,circle;
len=(""+n).length();
x=n/(int)Math.pow(10,len-1);
y=n%(int)Math.pow(10,len-1);
circle=(y*10)+x;
return circle;
/**
Another way using String
String str = Integer.toString(n);
String arr = str.substring(1)+str.charAt(0);
int a = Integer.parseInt(arr);
return a;
**/
}
public void check(int n)
{
int a=n;
boolean flag=true;
System.out.println("OUTPUT:");
do
{
if(!(prime(a)))
{
flag=false;
break;
}
a=circlize(a);
System.out.println(a);
}while(a!=n);
if(flag)System.out.println(n+" IS A CIRCULAR PRIME");
else System.out.println(n+" IS NOT A CIRCULAR PRIME");
}
public static void main(String ar[])
{
CircularPrime obj = new CircularPrime();
Scanner sc = new Scanner(System.in);
System.out.print("Enter a number: ");
int n=sc.nextInt();
obj.check(n);
}
}
My code tries to implement an algorithm to
take user input for two integer numbers and an operand + or - from the console,
store those numbers digit by digit in an int[50], representing negative ones in ten's complement format,
implement (decimal) digit-by-digit add/subtract operations,
print the result in decimal format without leading zeroes.
However, in my current implementation there are two problems
When adding 99 + 9999, the printed result is 01098 instead of the expected 010098.
When subtracting 99 - 9999, I get an ArrayIndexOutOfBoundsException: 50 instead of the expected result -09900.
import java.util.*;
public class Program9 {
public static String getOperand() {
Scanner scan = new Scanner(System.in);
String stringOfInteger;
System.out.print("Please enter an integer up to 50 numbers: ");
stringOfInteger = scan.nextLine();
return stringOfInteger;
}
public static int[] convert(String operand) {
int[] integer = new int[50];
char ch;
int position = operand.length() - 1;
for (int i = integer.length - 1; i >= 0; i--) {
if (position >= 0)
ch = operand.charAt(position--);
else
ch = 0;
if (ch >= '0' && ch <= '9') {
integer[i] = ch - '0';
} else {
integer[i] = 0;
}
}
return integer;
}
public static int[] add(int[] operand1, int[] operand2) {
int[] result = new int[operand1.length];
int carry = 0;
for (int i = operand1.length - 1; i >= 0; i--) {
result[i] = operand1[i] + operand2[i] + carry;
if (result[i] / 10 == 1) {
result[i] = result[i] % 10;
carry = 1;
} else
carry = 0;
}
return result;
}
public static int[] complement(int[] operand) {
int[] result = new int[operand.length];
for (int i = operand.length - 1; i >= 0; i--)
result[i] = 9 - operand[i];
return result;
}
public static int[] add1(int[] operand) {
int[] result = new int[50];
result[49] = 1;
for (int i = result.length - 2; i >= 0; i--)
result[i] = 0;
return result;
}
public static int[] negate(int[] operand) {
return add(add1(operand), complement(operand));
}
public static void print(int[] result, String operation) {
if (operation.charAt(0) == '+')
System.out.print("The subtotal of the two integer = ");
else if (operation.charAt(0) == '-')
System.out.print("The substraction of the two integers = ");
if (result[0] == 9) {
result = negate(result);
System.out.print("-");
for (int i = 0; i < result.length; i++) {
if (result[i] == 0 && result[i + 1] == 0)
continue;
else
System.out.print(result[i]);
}
} else
for (int i = 0; i < result.length; i++) {
if (result[i] == 0 && result[i + 1] == 0)
continue;
else
System.out.print(result[i]);
}
System.out.println();
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int[] result = new int[50];
String string1 = getOperand();
String string2 = getOperand();
int[] integer1 = convert(string1);
int[] integer2 = convert(string2);
String operation;
System.out.print("Please enter which operation will be used (+ or -): ");
operation = scan.nextLine();
if (operation.charAt(0) == '+')
add(integer1, integer2);
else if (operation.charAt(0) == '-')
integer2 = negate(integer2);
result = add(integer1, integer2);
System.out.println(Arrays.toString(integer1));
System.out.println(Arrays.toString(integer2));
System.out.println(Arrays.toString(add(integer1, integer2)));
print(result, operation);
}
}
Okay, after so much discussion and so many issues with your code I have totally revised your original code because you said you wanted to learn more. Among other improvements I have done the following changes:
Meaninfgul class name
Meaningful method and parameter names
Convert repeated and often used constants like 50 and the array representation of the number 1 (needed for negation) into static final members for clean code reasons (documentation, easy change in one place, meaningful names), runtime optimisation).
Extend the code to permit negative integers as operands
Added validation patterns for user input. E.g. now the maximum number length is checked in order to avoid an array overflow.
Avoid numeric overflows during calculation by making the array bigger than the maximum number of digits permitted for user input (see source code comments)
Add retry loops with error handling for operand and operator input, extract console handling into one parametrised method.
Simplify code by removing unnecessary checks because user input is already validated before converting it into an int[].
Make debug output optional
package de.scrum_master.stackoverflow;
import java.util.Arrays;
import java.util.Scanner;
import java.util.regex.Pattern;
public class TensComplementArithmetic {
// Print debug messages?
private static final boolean DEBUG = true;
// Maximum length for numbers entered by a user
// (number of digits excluding the optional +/- sign)
private static final int MAX_NUMBER_LENGTH = 50;
// Array must have one additional element for the sign and
// one more to avoid overflows when adding big negative numbers
private static final int ARRAY_LENGTH = MAX_NUMBER_LENGTH + 2;
// Scanner for console input handling
private static final Scanner INPUT_SCANNER = new Scanner(System.in);
// Regex pattern for positive/negative integer number format verification incl. length check
private static final Pattern INTEGER_PATTERN = Pattern.compile("[+-]?[0-9]{1," + MAX_NUMBER_LENGTH + "}");
// Regex pattern for operator verification (currently only "+"/"-" allowed)
private static final Pattern OPERATOR_PATTERN = Pattern.compile("[+-]");
// The number 1 is always needed for converting a 9's into a 10's complement
// during negation, so we define it as a reusable constant
private static final int[] NUMBER_ONE;
static {
// Initialise constant carrying array representation for number 1
NUMBER_ONE = new int[ARRAY_LENGTH];
NUMBER_ONE[ARRAY_LENGTH - 1] = 1;
}
public static String readConsoleInput(String prompt, Pattern validationPattern, String errorMessage) {
String input = null;
while (input == null) {
System.out.print(prompt + ": ");
if (INPUT_SCANNER.hasNext(validationPattern))
input = INPUT_SCANNER.next(validationPattern);
else {
INPUT_SCANNER.nextLine();
System.out.println(errorMessage);
}
}
return input;
}
public static String getOperand(String operandName) {
return readConsoleInput(
"Operand " + operandName,
INTEGER_PATTERN,
"Illegal number format, please enter a positive/negative integer of max. " + MAX_NUMBER_LENGTH + " digits."
);
}
private static String getOperator() {
return readConsoleInput(
"Arithmetical operator (+ or -)",
OPERATOR_PATTERN,
"Unknown operator, try again."
);
}
public static int[] parseInteger(String number) {
char sign = number.charAt(0);
boolean isNegative = sign == '-' ? true : false;
if (isNegative || sign == '+')
number = number.substring(1);
int[] result = new int[ARRAY_LENGTH];
int parsePosition = number.length() - 1;
for (int i = result.length - 1; i >= 0; i--) {
if (parsePosition < 0)
break;
result[i] = number.charAt(parsePosition--) - '0';
}
return isNegative ? negate(result) : result;
}
public static int[] add(int[] operand1, int[] operand2) {
int[] result = new int[ARRAY_LENGTH];
int carry = 0;
for (int i = ARRAY_LENGTH - 1; i >= 0; i--) {
result[i] = operand1[i] + operand2[i] + carry;
if (result[i] >= 10) {
result[i] = result[i] % 10;
carry = 1;
} else
carry = 0;
}
return result;
}
public static int[] complement(int[] operand) {
int[] result = new int[ARRAY_LENGTH];
for (int i = operand.length - 1; i >= 0; i--)
result[i] = 9 - operand[i];
return result;
}
public static int[] negate(int[] operand) {
return add(complement(operand), NUMBER_ONE);
}
public static void print(int[] result, String operation) {
System.out.print(operation.charAt(0) == '-' ? "Difference = " : "Sum = ");
if (result[0] == 9) {
result = negate(result);
System.out.print("-");
}
boolean leadingZero = true;
for (int i = 0; i < result.length; i++) {
if (leadingZero) {
if (result[i] == 0)
continue;
leadingZero = false;
}
System.out.print(result[i]);
}
System.out.println(leadingZero ? "0" : "");
}
public static void main(String[] args) {
int[] operand1 = parseInteger(getOperand("#1"));
int[] operand2 = parseInteger(getOperand("#2"));
String operator = getOperator();
if (operator.equals("-"))
operand2 = negate(operand2);
int[] result = new int[ARRAY_LENGTH];
result = add(operand1, operand2);
if (DEBUG) {
System.out.println("Operand #1 = " + Arrays.toString(operand1));
System.out.println("Operand #2 = " + Arrays.toString(operand2));
System.out.println("Result = " + Arrays.toString(result));
}
print(result, operator);
}
}
Disclaimer: Your source code has multiple problems, but in order to keep it simple I am going to ignore most of them now and will just explain the reasons for your current problems and suggest fixes for them only.
If you check the array outputs from your main method, you see that the addition/subtraction results look good, i.e. the problem is not located in the calculation routines but in the print routine. There you have
duplicate code: The for loops printing the positive/negative numbers are identical.
a cosmetic problem: One leading zero is always printed.
a logical error: You check for two consecutive zeroes in order to determine where leading zeroes end and the actual number begins. But you forget that
within a number there can also be duplicate zeroes, e.g. within 10098 or -9900. This explains why 10098 is printed as 1098: You are suppressing the first zero from being printed.
if there is a zero in the last array element (e.g. 9900) you cannot check the (non-existent) subsequent element without causing an ArrayIndexOutOfBoundsException. This explains why you get the exception for -9900.
Now what can/should you do?
Eliminate the redundant for loop. You can use the same loop to print both positive and negative numbers.
Use a boolean flag in order to remember if you are still looping through leading zeroes or not.
You can change your print method like so:
public static void print(int[] result, String operation) {
System.out.print(operation.charAt(0) == '-' ? "Difference = " : "Sum = ");
if (result[0] == 9) {
result = negate(result);
System.out.print("-");
}
boolean leadingZero = true;
for (int i = 0; i < result.length; i++) {
if (leadingZero) {
if (result[i] == 0)
continue;
leadingZero = false;
}
System.out.print(result[i]);
}
System.out.println(leadingZero ? "0" : "");
}
The code after fixing the problems. all thanks to #kriegaex !
import java.util.*;
public class Program9 {
public static String getOperand() {
Scanner scan = new Scanner(System.in);
String stringOfInteger;
System.out.print("Please enter an integer up to 50 numbers: ");
stringOfInteger = scan.nextLine();
return stringOfInteger;
}
public static int[] convert(String operand) {
int [] integer = new int[50];
char ch;
int position = operand.length() - 1;
for (int i = integer.length - 1; i >= 0; i--) {
if (position >= 0)
ch = operand.charAt(position--);
else
ch = 0;
if (ch >= '0' && ch <= '9') {
integer[i] = ch - '0';
} else {
integer[i] = 0;
}
}
return integer;
}
public static int[] add(int[] operand1, int[] operand2) {
int [] result = new int[operand1.length];
int carry = 0;
for (int i = operand1.length - 1; i >= 0; i--) {
result[i] = operand1[i] + operand2[i] + carry;
if (result[i] / 10 == 1) {
result[i] = result[i] % 10;
carry = 1;
} else
carry = 0;
}
return result;
}
public static int[] complement(int[] operand2){
int [] result = new int[operand2.length];
for (int i = operand2.length - 1; i >= 0; i--)
result[i] = 9 - operand2[i];
return result;
}
public static int[] add1(int[] operand2){
int [] result = new int[operand2.length];
result[operand2.length - 1] = 1;
for (int i = result.length - 2; i >= 0; i--)
result[i] = 0;
return result;
}
public static int[] negate(int[] operand2){
return add(add1(operand2), complement(operand2));
}
public static void print(int[] result, String operation) {
if (operation.charAt(0) == '+')
System.out.print("The subtotal of the two integers = ");
else if (operation.charAt(0) == '-')
System.out.print("The subtraction of the two integers = ");
if (result[0] == 9) {
result = negate(result);
System.out.print("-");
}
boolean leadingZero = true;
for (int i = 0; i < result.length; i++) {
if (leadingZero) {
if (result[i] == 0)
continue;
leadingZero = false;
}
System.out.print(result[i]);
}
if (leadingZero == true)
System.out.println('0' - '0');
System.out.println();
}
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int [] result = new int[50];
String string1 = getOperand();
String string2 = getOperand();
int [] integer1 = convert(string1);
int [] integer2 = convert(string2);
String operation;
System.out.print("Please enter which operation will be used (+ or -): ");
operation = scan.nextLine();
if (operation.charAt(0) == '+')
add(integer1, integer2);
else if (operation.charAt(0) == '-')
integer2 = negate(integer2);
result = add(integer1, integer2);
System.out.println(Arrays.toString(integer1));
System.out.println(Arrays.toString(integer2));
System.out.println(Arrays.toString(add(integer1, integer2)));
print(result, operation);
}
}
I need to convert a large decimal to binary how would I go about doing this? Decimal in question is this 3324679375210329505
How about:
String binary = Long.toString(3324679375210329505L, 2);
You may want to go for BigDecimal.
A BigDecimal consists of an arbitrary
precision integer unscaled value and a
32-bit integer scale.The BigDecimal class provides operations for arithmetic, scale
manipulation, rounding, comparison, hashing, and format conversion. The toString() method
provides a canonical representation of a BigDecimal.
new BigDecimal("3324679375210329505").toString(2);
http://www.wikihow.com/Convert-from-Decimal-to-Binary
I would use a Stack! Check if your decimal number is even or odd, if even push a 0 to the stack and if its odd push a 1 to the stack. Then once your decimal number hits 1, you can pop each value from the stack and print each one.
Here is a very inefficient block of code for reference. You will probably have to use long instead of integer.
import java.util.Stack;
public class DecBinConverter {
Stack<Integer> binary;
public DecBinConverter()
{
binary = new Stack<Integer>();
}
public int dec_Bin(int dec)
{
if(dec == 1)
{
System.out.print(1);
return 0;
}
if(dec == 0)
{
System.out.print(0);
return 0;
}
if((dec%2) == 0)
{
binary.push(0);
dec = dec/2;
}
else
{
binary.push(1);
dec = dec/2;
}
while(dec != 1)
{
if((dec%2) == 0)
{
binary.push(0);
dec = dec/2;
}
else
{
binary.push(1);
dec = dec/2;
}
}
if((dec%2) == 0)
{
binary.push(0);
dec = dec/2;
}
else
{
binary.push(1);
dec = dec/2;
}
int x = binary.size();
for(int i = 0; i < x; i++)
{
System.out.print(binary.pop());
}
return 0;
}
}
If you want something fast (over 50% faster than Long.toString(n, 2) and 150-400% faster than BigInteger.toString(2)) that handles negative numbers the same as the built-ins, try the following:
static String toBinary (long n) {
int neg = n < 0 ? 1 : 0;
if(n < 0) n = -n;
int pos = 0;
boolean[] a = new boolean[64];
do {
a[pos++] = n % 2 == 1;
} while ((n >>>= 1) != 0);
char[] c = new char[pos + neg];
if(neg > 0) c[0] = '-';
for (int i = 0; i < pos; i++) {
c[pos - i - 1 + neg] = a[i] ? '1' : '0';
}
return new String(c);
}
If you want the actual Two's Compliment binary representation of the long (with leading 1s or 0s):
static String toBinaryTC (long n) {
char[] c = new char[64];
for(int i = 63; i >= 0; i--, n >>>= 1) {
c[i] = n % 2 != 0 ? '1' : '0';
}
return new String(c);
}
A bit pointless, but here is a solution in C:
void to_binary(unsigned long long n)
{
char str[65], *ptr = str + 1;
str[0] = '\n';
do{
*ptr++ = '0' + (n&1);
} while(n >>= 1);
while(ptr > str)
putc(*--ptr, stdout);
}
For the example, it prints out:
10111000100011101000100100011011011111011110101011010110100001
EDIT: And if you don't mind leading zeros....
void to_binary(unsigned long long n)
{
do{ putc('0' + (n>>63), stdout); } while(n <<= 1);
}
Pandigital number is a number that contains the digits 1..number length.
For example 123, 4312 and 967412385.
I have solved many Project Euler problems, but the Pandigital problems always exceed the one minute rule.
This is my pandigital function:
private boolean isPandigital(int n){
Set<Character> set= new TreeSet<Character>();
String string = n+"";
for (char c:string.toCharArray()){
if (c=='0') return false;
set.add(c);
}
return set.size()==string.length();
}
Create your own function and test it with this method
int pans=0;
for (int i=123456789;i<=123987654;i++){
if (isPandigital(i)){
pans++;
}
}
Using this loop, you should get 720 pandigital numbers. My average time was 500 millisecond.
I'm using Java, but the question is open to any language.
UPDATE
#andras answer has the best time so far, but #Sani Huttunen answer inspired me to add a new algorithm, which gets almost the same time as #andras.
C#, 17ms, if you really want a check.
class Program
{
static bool IsPandigital(int n)
{
int digits = 0; int count = 0; int tmp;
for (; n > 0; n /= 10, ++count)
{
if ((tmp = digits) == (digits |= 1 << (n - ((n / 10) * 10) - 1)))
return false;
}
return digits == (1 << count) - 1;
}
static void Main()
{
int pans = 0;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 123456789; i <= 123987654; i++)
{
if (IsPandigital(i))
{
pans++;
}
}
sw.Stop();
Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds);
Console.ReadKey();
}
}
For a check that is consistent with the Wikipedia definition in base 10:
const int min = 1023456789;
const int expected = 1023;
static bool IsPandigital(int n)
{
if (n >= min)
{
int digits = 0;
for (; n > 0; n /= 10)
{
digits |= 1 << (n - ((n / 10) * 10));
}
return digits == expected;
}
return false;
}
To enumerate numbers in the range you have given, generating permutations would suffice.
The following is not an answer to your question in the strict sense, since it does not implement a check. It uses a generic permutation implementation not optimized for this special case - it still generates the required 720 permutations in 13ms (line breaks might be messed up):
static partial class Permutation
{
/// <summary>
/// Generates permutations.
/// </summary>
/// <typeparam name="T">Type of items to permute.</typeparam>
/// <param name="items">Array of items. Will not be modified.</param>
/// <param name="comparer">Optional comparer to use.
/// If a <paramref name="comparer"/> is supplied,
/// permutations will be ordered according to the
/// <paramref name="comparer"/>
/// </param>
/// <returns>Permutations of input items.</returns>
public static IEnumerable<IEnumerable<T>> Permute<T>(T[] items, IComparer<T> comparer)
{
int length = items.Length;
IntPair[] transform = new IntPair[length];
if (comparer == null)
{
//No comparer. Start with an identity transform.
for (int i = 0; i < length; i++)
{
transform[i] = new IntPair(i, i);
};
}
else
{
//Figure out where we are in the sequence of all permutations
int[] initialorder = new int[length];
for (int i = 0; i < length; i++)
{
initialorder[i] = i;
}
Array.Sort(initialorder, delegate(int x, int y)
{
return comparer.Compare(items[x], items[y]);
});
for (int i = 0; i < length; i++)
{
transform[i] = new IntPair(initialorder[i], i);
}
//Handle duplicates
for (int i = 1; i < length; i++)
{
if (comparer.Compare(
items[transform[i - 1].Second],
items[transform[i].Second]) == 0)
{
transform[i].First = transform[i - 1].First;
}
}
}
yield return ApplyTransform(items, transform);
while (true)
{
//Ref: E. W. Dijkstra, A Discipline of Programming, Prentice-Hall, 1997
//Find the largest partition from the back that is in decreasing (non-icreasing) order
int decreasingpart = length - 2;
for (;decreasingpart >= 0 &&
transform[decreasingpart].First >= transform[decreasingpart + 1].First;
--decreasingpart) ;
//The whole sequence is in decreasing order, finished
if (decreasingpart < 0) yield break;
//Find the smallest element in the decreasing partition that is
//greater than (or equal to) the item in front of the decreasing partition
int greater = length - 1;
for (;greater > decreasingpart &&
transform[decreasingpart].First >= transform[greater].First;
greater--) ;
//Swap the two
Swap(ref transform[decreasingpart], ref transform[greater]);
//Reverse the decreasing partition
Array.Reverse(transform, decreasingpart + 1, length - decreasingpart - 1);
yield return ApplyTransform(items, transform);
}
}
#region Overloads
public static IEnumerable<IEnumerable<T>> Permute<T>(T[] items)
{
return Permute(items, null);
}
public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> items, IComparer<T> comparer)
{
List<T> list = new List<T>(items);
return Permute(list.ToArray(), comparer);
}
public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> items)
{
return Permute(items, null);
}
#endregion Overloads
#region Utility
public static IEnumerable<T> ApplyTransform<T>(
T[] items,
IntPair[] transform)
{
for (int i = 0; i < transform.Length; i++)
{
yield return items[transform[i].Second];
}
}
public static void Swap<T>(ref T x, ref T y)
{
T tmp = x;
x = y;
y = tmp;
}
public struct IntPair
{
public IntPair(int first, int second)
{
this.First = first;
this.Second = second;
}
public int First;
public int Second;
}
#endregion
}
class Program
{
static void Main()
{
int pans = 0;
int[] digits = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
Stopwatch sw = new Stopwatch();
sw.Start();
foreach (var p in Permutation.Permute(digits))
{
pans++;
if (pans == 720) break;
}
sw.Stop();
Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds);
Console.ReadKey();
}
}
This is my solution:
static char[][] pandigits = new char[][]{
"1".toCharArray(),
"12".toCharArray(),
"123".toCharArray(),
"1234".toCharArray(),
"12345".toCharArray(),
"123456".toCharArray(),
"1234567".toCharArray(),
"12345678".toCharArray(),
"123456789".toCharArray(),
};
private static boolean isPandigital(int i)
{
char[] c = String.valueOf(i).toCharArray();
Arrays.sort(c);
return Arrays.equals(c, pandigits[c.length-1]);
}
Runs the loop in 0.3 seconds on my (rather slow) system.
Two things you can improve:
You don't need to use a set: you can use a boolean array with 10 elements
Instead of converting to a string, use division and the modulo operation (%) to extract the digits.
Using a bit vector to keep track of which digits have been found appears to be the fastest raw method. There are two ways to improve it:
Check if the number is divisible by 9. This is a necessary condition for being pandigital, so we can exclude 88% of numbers up front.
Use multiplication and shifts instead of divisions, in case your compiler doesn't do that for you.
This gives the following, which runs the test benchmark in about 3ms on my machine. It correctly identifies the 362880 9-digit pan-digital numbers between 100000000 and 999999999.
bool IsPandigital(int n)
{
if (n != 9 * (int)((0x1c71c71dL * n) >> 32))
return false;
int flags = 0;
while (n > 0) {
int q = (int)((0x1999999aL * n) >> 32);
flags |= 1 << (n - q * 10);
n = q;
}
return flags == 0x3fe;
}
My solution involves Sums and Products.
This is in C# and runs in about 180ms on my laptop:
static int[] sums = new int[] {1, 3, 6, 10, 15, 21, 28, 36, 45};
static int[] products = new int[] {1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
static void Main(string[] args)
{
var pans = 0;
for (var i = 123456789; i <= 123987654; i++)
{
var num = i.ToString();
if (Sum(num) == sums[num.Length - 1] && Product(num) == products[num.Length - 1])
pans++;
}
Console.WriteLine(pans);
}
protected static int Sum(string num)
{
int sum = 0;
foreach (char c in num)
sum += (int) (c - '0');
return sum;
}
protected static int Product(string num)
{
int prod = 1;
foreach (char c in num)
prod *= (int)(c - '0');
return prod;
}
Why find when you can make them?
from itertools import *
def generate_pandigital(length):
return (''.join for each in list(permutations('123456789',length)))
def test():
for i in range(10):
print i
generate_pandigital(i)
if __name__=='__main__':
test()
J does this nicely:
isPandigital =: 3 : 0
*./ (' ' -.~ ": 1 + i. # s) e. s =. ": y
)
isPandigital"0 (123456789 + i. 1 + 123987654 - 123456789)
But slowly. I will revise. For now, clocking at 4.8 seconds.
EDIT:
If it's just between the two set numbers, 123456789 and 123987654, then this expression:
*./"1 (1+i.9) e."1 (9#10) #: (123456789 + i. 1 + 123987654 - 123456789)
Runs in 0.23 seconds. It's about as fast, brute-force style, as it gets in J.
TheMachineCharmer is right. At least for some the problems, it's better to iterate over all the pandigitals, checking each one to see if it fits the criteria of the problem. However, I think their code is not quite right.
I'm not sure which is better SO etiquette in this case: Posting a new answer or editing theirs. In any case, here is the modified Python code which I believe to be correct, although it doesn't generate 0-to-n pandigitals.
from itertools import *
def generate_pandigital(length):
'Generate all 1-to-length pandigitals'
return (''.join(each) for each in list(permutations('123456789'[:length])))
def test():
for i in range(10):
print 'Generating all %d-digit pandigitals' % i
for (n,p) in enumerate(generate_pandigital(i)):
print n,p
if __name__=='__main__':
test()
You could add:
if (set.add(c)==false) return false;
This would short circuit a lot of your computations, since it'll return false as soon as a duplicate was found, since add() returns false in this case.
bool IsPandigital (unsigned long n) {
if (n <= 987654321) {
hash_map<int, int> m;
unsigned long count = (unsigned long)(log((double)n)/log(10.0))+1;
while (n) {
++m[n%10];
n /= 10;
}
while (m[count]==1 && --count);
return !count;
}
return false;
}
bool IsPandigital2 (unsigned long d) {
// Avoid integer overflow below if this function is passed a very long number
if (d <= 987654321) {
unsigned long sum = 0;
unsigned long prod = 1;
unsigned long n = d;
unsigned long max = (log((double)n)/log(10.0))+1;
unsigned long max_sum = max*(max+1)/2;
unsigned long max_prod = 1;
while (n) {
sum += n % 10;
prod *= (n%10);
max_prod *= max;
--max;
n /= 10;
}
return (sum == max_sum) && (prod == max_prod);
}
I have a solution for generating Pandigital numbers using StringBuffers in Java. On my laptop, my code takes a total of 5ms to run. Of this only 1ms is required for generating the permutations using StringBuffers; the remaining 4ms are required for converting this StringBuffer to an int[].
#medopal: Can you check the time this code takes on your system?
public class GenPandigits
{
/**
* The prefix that must be appended to every number, like 123.
*/
int prefix;
/**
* Length in characters of the prefix.
*/
int plen;
/**
* The digit from which to start the permutations
*/
String beg;
/**
* The length of the required Pandigital numbers.
*/
int len;
/**
* #param prefix If there is no prefix then this must be null
* #param beg If there is no prefix then this must be "1"
* #param len Length of the required numbers (excluding the prefix)
*/
public GenPandigits(String prefix, String beg, int len)
{
if (prefix == null)
{
this.prefix = 0;
this.plen = 0;
}
else
{
this.prefix = Integer.parseInt(prefix);
this.plen = prefix.length();
}
this.beg = beg;
this.len = len;
}
public StringBuffer genPermsBet()
{
StringBuffer b = new StringBuffer(beg);
for(int k=2;k<=len;k++)
{
StringBuffer rs = new StringBuffer();
int l = b.length();
int s = l/(k-1);
String is = String.valueOf(k+plen);
for(int j=0;j<k;j++)
{
rs.append(b);
for(int i=0;i<s;i++)
{
rs.insert((l+s)*j+i*k+j, is);
}
}
b = rs;
}
return b;
}
public int[] getPandigits(String buffer)
{
int[] pd = new int[buffer.length()/len];
int c= prefix;
for(int i=0;i<len;i++)
c =c *10;
for(int i=0;i<pd.length;i++)
pd[i] = Integer.parseInt(buffer.substring(i*len, (i+1)*len))+c;
return pd;
}
public static void main(String[] args)
{
GenPandigits gp = new GenPandigits("123", "4", 6);
//GenPandigits gp = new GenPandigits(null, "1", 6);
long beg = System.currentTimeMillis();
StringBuffer pansstr = gp.genPermsBet();
long end = System.currentTimeMillis();
System.out.println("Time = " + (end - beg));
int pd[] = gp.getPandigits(pansstr.toString());
long end1 = System.currentTimeMillis();
System.out.println("Time = " + (end1 - end));
}
}
This code can also be used for generating all Pandigital numbers(excluding zero). Just change the object creation call to
GenPandigits gp = new GenPandigits(null, "1", 9);
This means that there is no prefix, and the permutations must start from "1" and continue till the length of the numbers is 9.
Following are the time measurements for different lengths.
#andras: Can you try and run your code to generate the nine digit Pandigital numbers? What time does it take?
This c# implementation is about 8% faster than #andras over the range 123456789 to 123987654 but it is really difficult to see on my test box as his runs in 14ms and this one runs in 13ms.
static bool IsPandigital(int n)
{
int count = 0;
int digits = 0;
int digit;
int bit;
do
{
digit = n % 10;
if (digit == 0)
{
return false;
}
bit = 1 << digit;
if (digits == (digits |= bit))
{
return false;
}
count++;
n /= 10;
} while (n > 0);
return (1<<count)-1 == digits>>1;
}
If we average the results of 100 runs we can get a decimal point.
public void Test()
{
int pans = 0;
var sw = new Stopwatch();
sw.Start();
for (int count = 0; count < 100; count++)
{
pans = 0;
for (int i = 123456789; i <= 123987654; i++)
{
if (IsPandigital(i))
{
pans++;
}
}
}
sw.Stop();
Console.WriteLine("{0}pcs, {1}ms", pans, sw.ElapsedMilliseconds / 100m);
}
#andras implementation averages 14.4ms and this implementation averages 13.2ms
EDIT:
It seems that mod (%) is expensive in c#. If we replace the use of the mod operator with a hand coded version then this implementation averages 11ms over 100 runs.
private static bool IsPandigital(int n)
{
int count = 0;
int digits = 0;
int digit;
int bit;
do
{
digit = n - ((n / 10) * 10);
if (digit == 0)
{
return false;
}
bit = 1 << digit;
if (digits == (digits |= bit))
{
return false;
}
count++;
n /= 10;
} while (n > 0);
return (1 << count) - 1 == digits >> 1;
}
EDIT: Integrated n/=10 into the digit calculation for a small speed improvement.
private static bool IsPandigital(int n)
{
int count = 0;
int digits = 0;
int digit;
int bit;
do
{
digit = n - ((n /= 10) * 10);
if (digit == 0)
{
return false;
}
bit = 1 << digit;
if (digits == (digits |= bit))
{
return false;
}
count++;
} while (n > 0);
return (1 << count) - 1 == digits >> 1;
}
#include <cstdio>
#include <ctime>
bool isPandigital(long num)
{
int arr [] = {1,2,3,4,5,6,7,8,9}, G, count = 9;
do
{
G = num%10;
if (arr[G-1])
--count;
arr[G-1] = 0;
} while (num/=10);
return (!count);
}
int main()
{
clock_t start(clock());
int pans=0;
for (int i = 123456789;i <= 123987654; ++i)
{
if (isPandigital(i))
++pans;
}
double end((double)(clock() - start));
printf("\n\tFound %d Pandigital numbers in %lf seconds\n\n", pans, end/CLOCKS_PER_SEC);
return 0;
}
Simple implementation. Brute-forced and computes in about 140 ms
In Java
You can always just generate them, and convert the Strings to Integers, which is faster for larger numbers
public static List<String> permutation(String str) {
List<String> permutations = new LinkedList<String>();
permutation("", str, permutations);
return permutations;
}
private static void permutation(String prefix, String str, List<String> permutations) {
int n = str.length();
if (n == 0) {
permutations.add(prefix);
} else {
for (int i = 0; i < n; i++) {
permutation(prefix + str.charAt(i),
str.substring(0, i) + str.substring(i + 1, n), permutations);
}
}
}
The below code works for testing a numbers pandigitality.
For your test mine ran in around ~50ms
1-9 PanDigital
public static boolean is1To9PanDigit(int i) {
if (i < 1e8) {
return false;
}
BitSet set = new BitSet();
while (i > 0) {
int mod = i % 10;
if (mod == 0 || set.get(mod)) {
return false;
}
set.set(mod);
i /= 10;
}
return true;
}
or more general, 1 to N,
public static boolean is1ToNPanDigit(int i, int n) {
BitSet set = new BitSet();
while (i > 0) {
int mod = i % 10;
if (mod == 0 || mod > n || set.get(mod)) {
return false;
}
set.set(mod);
i /= 10;
}
return set.cardinality() == n;
}
And just for fun, 0 to 9, zero requires extra logic due to a leading zero
public static boolean is0To9PanDigit(long i) {
if (i < 1e6) {
return false;
}
BitSet set = new BitSet();
if (i <= 123456789) { // count for leading zero
set.set(0);
}
while (i > 0) {
int mod = (int) (i % 10);
if (set.get(mod)) {
return false;
}
set.set(mod);
i /= 10;
}
return true;
}
Also for setting iteration bounds:
public static int maxPanDigit(int n) {
StringBuffer sb = new StringBuffer();
for(int i = n; i > 0; i--) {
sb.append(i);
}
return Integer.parseInt(sb.toString());
}
public static int minPanDigit(int n) {
StringBuffer sb = new StringBuffer();
for(int i = 1; i <= n; i++) {
sb.append(i);
}
return Integer.parseInt(sb.toString());
}
You could easily use this code to generate a generic MtoNPanDigital number checker
I decided to use something like this:
def is_pandigital(n, zero_full=True, base=10):
"""Returns True or False if the number n is pandigital.
This function returns True for formal pandigital numbers as well as
n-pandigital
"""
r, l = 0, 0
while n:
l, r, n = l + 1, r + n % base, n / base
t = xrange(zero_full ^ 1, l + (zero_full ^ 1))
return r == sum(t) and l == len(t)
Straight forward way
boolean isPandigital(int num,int length){
for(int i=1;i<=length;i++){
if(!(num+"").contains(i+""))
return false;
}
return true;
}
OR if you are sure that the number is of the right length already
static boolean isPandigital(int num){
for(int i=1;i<=(num+"").length();i++){
if(!(num+"").contains(i+""))
return false;
}
return true;
}
I refactored Andras' answer for Swift:
extension Int {
func isPandigital() -> Bool {
let requiredBitmask = 0b1111111111;
let minimumPandigitalNumber = 1023456789;
if self >= minimumPandigitalNumber {
var resultBitmask = 0b0;
var digits = self;
while digits != 0 {
let lastDigit = digits % 10;
let binaryCodedDigit = 1 << lastDigit;
resultBitmask |= binaryCodedDigit;
// remove last digit
digits /= 10;
}
return resultBitmask == requiredBitmask;
}
return false;
}
}
1023456789.isPandigital(); // true
great answers, my 2 cents
bool IsPandigital(long long number, int n){
int arr[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, amax = 0, amin;
while (number > 0){
int rem = number % 10;
arr[rem]--;
if (arr[rem] < 0)
return false;
number = number / 10;
}
for (int i = 0; i < n; i++){
if (i == 0)
amin = arr[i];
if (arr[i] > amax)
amax = arr[i];
if (arr[i] < amin)
amin = arr[i];
}
if (amax == 0 && amin == 0)
return true;
else
return false;
}