any java programmers out there?
The assignment, from Thinking in Java by Bruce Eckel:
A vampire number has an even number of digits and is formed by multiplying a pair of numbers containing half the number of digits as the results. The digits are taken from the original number in any order. Pairs of trailing zeros are not allowed. Examples include:
1260=21*60
1827=21*87
2187=27*81
Write a program that finds all the 4-digit vampire numbers."
so I wrote this from scratch. It works, and produces the correct result, but I'm sure there is a more elegant way of doing it- especially with getArrayOfDigits(). I don't know if there are any java developers who read my blog, but if there are, a little criticism would be appreciated.
import static net.mindview.util.Print.*;
// the print() method is identical to System.out.println().
public class Exercise10 {
public static void main(String[] args) {
for (int i=1000; i<10000;i++ )
{
if(i%100==0) continue; //weed out the numbers with two trailing zeros
int[] result = isVampire(i);
if(result != null) {
print(result[0] + "*" + result[1] + "=" + i + ". It's a vampire number");
}
}
}
private static int[] getArrayOfDigits(int i) {
//I am sure this can be done better
int[] a = {0,0,0,0};
a[0] = ((int)i/1000);
i=i-a[0]*1000;
a[1] = ((int)i/100);
i=i-a[1]*100;
a[2] = ((int)i/10);
a[3]=i-a[2]*10;
return a;
}
private static int[] isVampire(int i) {
int[] arr = getArrayOfDigits(i);
for(int a=0; a<=3;a++) {
for (int b=0;b<=3 ;b++ ) {
if(a==b) continue;
for (int c=0;c<=3 ;c++ ) {
if(a==c) continue;
if(b==c) continue;
for (int d=0;d<=3 ;d++ ) {
if(a==d) continue;
if(b==d) continue;
if(c==d) continue; //this series of continues can probably be done better, too.
if(GetTestNumber(arr[a],arr[b]) * GetTestNumber(arr[c],arr[d]) == i) {
int[] done={GetTestNumber(arr[a],arr[b]), GetTestNumber(arr[c],arr[d])};
return done;
}
}
}
}
}
return null;
}
private static int GetTestNumber(int a, int b) {
return ((a*10)+b);
}
}
thanks..
-steve
I actually have the same book and have been a programmer for 3 days now :-) I have no idea which way is better but I took a very different approach so I thought I would share it. I converted the numbers to a string and then use the built in toCharArray() method. I also started with the two 2 digit numbers.
ReplyDeleteimport static net.mindview.util.Print.*;
import java.util.*;
public class Vampire {
public static boolean isVampire(int mult1, int mult2) {
int whole = (mult1 * mult2);
String wholeString = Integer.toString(whole);
String mult1String = Integer.toString(mult1);
String mult2String = Integer.toString(mult2);
String multString = mult1String + mult2String;
char[] wholeArray = wholeString.toCharArray();
char[] multArray = multString.toCharArray();
//used to keep track of where we are in the array. increments every time we get a match
int removeChar = 0;
//arrays used to make sure we discard chars when we match them up
int[] iArray = {5, 5, 5, 5};
int[] jArray = {5, 5, 5, 5};
//main loop to test each char in wholeArray against char in multArray 1 by 1
iLoop:
for(int i = 0; i < 4; i++) {
//no reason to keep checking once we miss a match
if((removeChar < i)) {
break;
}
for(int p = 0; p < 4; p++) {
//if this array spot already has a match skip it. not an efficiency thing. it avoids dups.
if(i == iArray[p]) {
continue iLoop;
}
}
jLoop:
for(int j = 0; j < 4; j++) {
for(int q = 0; q < 4; q++) {
//if this array spot already has a match skip it. not an efficiency thing. it avoids dups.
if(j == jArray[q]) {
continue jLoop;
}
}
if(wholeArray[i] == multArray[j]) {
//load the char array position when we find a match so we skip those later
iArray[removeChar] = i;
jArray[removeChar] = j;
removeChar++;
//these array locations can't be used again so continue in the outer loop
continue iLoop;
}
}
}
//if we replace all the 5s in the array we have a vampire
if(iArray[3] != 5) {
return true;
} else {
return false;
}
}
public static void main(String[] args) {
//lists that vampire numbers will be added to and checked for twins
ArrayList<Integer> twinListx = new ArrayList<Integer>();
ArrayList<Integer> twinListy = new ArrayList<Integer>();
//main loop. check every 2 digit number with ever 2 digit number
for(int x = 10; x < 100; x++) {
//secondary main loop. label used for twin continues
yLoop:
for(int y = 10; y < 100; y++) {
//we only want 4 digit vampires
if(((x * y) < 1000)||((x * y) > 9999))
continue;
//check to see if y and x exist in the same position in the opposite arrays - this removes duplicate results
for(int g = 0; (twinListx.size() != 0)&&(g < twinListx.size()); g++) {
if((twinListx.get(g) == y)&&(twinListy.get(g) == x))
continue yLoop;
}
//use isVampire method to see if the combo makes a vampire
if(isVampire(x, y)) {
print((x * y) + " = " + x + " * " + y + " is a vampire number!");
twinListx.add(x);
twinListy.add(y);
} else {
continue;
}
}
}
}
}
Steve, I saw that exercise and I think your approach is simpler than shanegary. You use only the knowledge until that chapter.
ReplyDeleteSorry for bad English.
This is late response, but for future reference to other people starting out like me, it might be helpful to see more different solution.
ReplyDeleteMy solution is similar to flasfs
but what I did was convert the
fangs and vampire number to char
array, then sorted them, and
compared.
BTW : this method is brute force.
Here is the code :
//package random_practice;
/* This program produces all fangs and its corresponding vampire number
from fang degree 2( ex 15 * 93) to the variable fangDeg (see below)
*/
import java.util.Arrays;
public class Main {
public static void print(Object obj){
System.out.print(obj);
}
public static void print() {
System.out.println();
}
static public boolean vampSrch(int f, int s, int res){
/* Convert f and s int char array as well as res to char array */
String str = Integer.toString(f);
str += Integer.toString(s);
char[] C = new char[5];
C = str.toCharArray();
Arrays.sort(C);
String str2 = Integer.toString(res);
char[] C2 = new char[str2.length() + 1];
C2 = str2.toCharArray();
//Sort array to start test
Arrays.sort(C2);
//check if worth testing
if( C.length != C2.length) return false;
//test each character to similarity
for(int i = 0; i < C.length ; i++)
if( C[i] != C2[i])
return false;
return true;
}
public static void main(String[] args)
{
int i = 10;
int j = 10;
//change this if you want to find a n variable degree fang
int fangsDeg = 2;// 2nd degreed fangs
int totFangs = 0;
int iLim = 1;
int maxLim = 1;
while(fangsDeg > 0){
iLim *= 10;
fangsDeg--;
}
maxLim = iLim * 100 - 1;
while(i <= iLim )
{
if( i*j > maxLim ){
i++;
j = 10;
}
if( vampSrch(i,j,i*j)){
print(i + "*" + j + " = " + i*j + "\n");
totFangs++;
//Check for no repeat
if( i / 10 > j/10)
break;
}
j++;
}
print("\nThe total number of fangs is " + totFangs + "\n\n");
}
}
Here is my version:
ReplyDeletepublic class Main {
static boolean VampN(int x, int y) {
if( Integer.toString(x*y).length()==4 ) {
int[] d = {x*y/1000,(x*y-(x*y/1000)*1000)/100,(x*y-(x*y/100)*100)/10,x*y-(x*y/10)*10};
int[] di = {0,0,0,0};
for (int i=0; i<4; i++)
if(x/10 == d[i] && di[i] == 0) {
di[i]=1;
break;
}
for (int i=0; i<4; i++)
if(x-(x/10)*10 == d[i] && di[i] == 0) {
di[i]=1;
break;
}
for (int i=0; i<4; i++)
if(y/10 == d[i] && di[i] == 0) {
di[i]=1;
break;
}
for (int i=0; i<4; i++)
if(y-(y/10)*10 == d[i] && di[i] == 0) {
di[i]=1;
break;
}
for (int i=0; i<4; i++)
if(di[i]==0) return false;
}
else
return false;
return true;
}
public static void main(String[] args) {
// TODO code application logic here
for( int i=10; i<=99; i++)
for(int j=10; j<=99; j++)
if (VampN(i, j))
System.out.println(i+" x "+j+" = "+(i*j));
}
}
public class VampNumbers {
ReplyDelete//method to join two single digits into a two digit number
static int join(int x, int y){
return(x * 10) + y;
}
//method to print vampire number if two derived numbers are equal to original
static void printVamp(int i, int x, int y){
if((x*y)==i){
System.out.println(i + " is a vampire number");
}
}
public static void main(String[] args) {
for(int i = 1000; i <=9999; i++){
//break 4 digit number into single digits
int a = i / 1000;
int b = (i % 1000) / 100;
int c = ((i % 1000) % 100) / 10;
int d = ((i % 1000) % 100) % 10;
//send all variations of multiplication to the printVamp method
printVamp(i, join(a, b), join(c, d));
printVamp(i, join(a, b), join(d, c));
printVamp(i, join(a, c), join(b, d));
printVamp(i, join(a, c), join(d, b));
printVamp(i, join(a, d), join(b, c));
printVamp(i, join(a, d), join(c, b));
printVamp(i, join(b, a), join(c, d));
printVamp(i, join(b, a), join(d, c));
printVamp(i, join(b, c), join(d, a));
printVamp(i, join(b, d), join(c, a));
printVamp(i, join(c, a), join(d, b));
printVamp(i, join(c, b), join(d, a));
}
}
}
I prefer simple very simple and easy to understand coding. I hope this helps :)
ReplyDeleteimport java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
/**
*
* @author Abhinav Mathur
*/
class NewClass3
{
public static void main(String args[]) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int e=0;
System.out.print("Enter 1st two digit number = ");
int a = Integer.parseInt(br.readLine());
System.out.print("Enter 2nd two digit number = ");
int b = Integer.parseInt(br.readLine());
int c=a*b;
int f=c;
int d=a*100+b;
for(int i=0;i<4;i++)
{
int num1=d%10;
d=d/10;
c=f;
for(int j=0;j<4;j++)
{
int num2=c%10;
c=c/10;
if(num1==num2)
{
e++;
}
}
}
if(e==4)
{
System.out.println("VAMPIRE NUMBER");
}
else{
System.out.print("NOT A VAMPIRE NUMBER");
}
}
}