I have a list of 75200 words. I need to give a 'unique' id to each word, and the length of each id could be 3 letters or less. I can use numbers, letters or even symbols but the max length is 3.
Below is my code.
import java.io.*;
import java.util.*;
public class HashCreator {
private Map completedWordMap;
private String [] simpleLetters = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
private String[] symbols = {"!","#","#","$","%","^","&","*","~","?"};
private String indexNumber;
String currentlyUsingLetter, currentlyUsingSymbol;
private int currentlyActiveSimpleLetter = 0, currentlyActiveSymbol = 0, currentlyActiveSimpleLetter2 = 0, currentlyActiveSymbol2 = 0;
private boolean secondaryNumberIsHundred = false;
public HashCreator()
{
completedWordMap = createWordNumberingMap();
}
private Map createWordNumberingMap()
{
int number = 0;
int secondaryNumber = 0;
int thirdinoryNumber = 0;
Map wordMap = new HashMap();
BufferedReader br = null;
String str = "";
boolean reset = false;
//First Read The File
File readingFile = new File("WordList/NewWordsList.txt");
try
{
br = new BufferedReader(new FileReader(readingFile));
while((str=br.readLine())!=null)
{
if(number<1000) //Asign numbers from 0 t0 999
{
indexNumber = String.valueOf(number);
wordMap.put(indexNumber, str);
number++;
System.out.println(indexNumber);
}
else // It is 1000 now. Length exceeds so find another way.
{
if(indexNumber.length()<4)
{
if(currentlyActiveSimpleLetter<simpleLetters.length) //Start using simple letter array
{
if(secondaryNumber<100) //Start combining numbers with letters. Results will look like 'a0', a1', 'a2'......'x98',x99'
{
indexNumber = simpleLetters[currentlyActiveSimpleLetter]+secondaryNumber;
wordMap.put(indexNumber, str);
secondaryNumber++;
System.out.println(indexNumber);
}
else
{
//If the number is 100, that means the last result is something like 'a99','b99'...'x99'
//Time to use a new letter and set the counter back to 0 and select the next letter
secondaryNumber = 0;
currentlyActiveSimpleLetter++;
}
}
else
{
if(currentlyActiveSymbol<symbols.length) //We have used the entire alphabet. Start using sybmols now.
{
if(currentlyActiveSymbol==0) //If this is the first time we are reaching this step, reset the counter to 0
{
secondaryNumber = 0;
}
if(secondaryNumber<100)
{
indexNumber = symbols[currentlyActiveSymbol]+secondaryNumber;
wordMap.put(indexNumber, str);
secondaryNumber++;
System.out.println(indexNumber);
}
else
{
//If the number is 100, that means the last result is something like '!99','#99'...'*99'
//Time to use a new letter and set the counter back to 0 and select the next symbol
secondaryNumber = 0;
currentlyActiveSymbol++;
}
}
else
{
//We have used entire list of numbers (0-999), entire list of letters (a0-z99) and entire set of symbols (!0 - ?99)
//Now we need to combine all 3 together.
if(thirdinoryNumber<10)//We are starting with a new 'Number' counter
{
//We again start with replacing numbers. Here the first few and last few results will look like a!0'.....'a!9'
indexNumber = simpleLetters[currentlyActiveSimpleLetter2]+symbols[currentlyActiveSymbol]+thirdinoryNumber;
wordMap.put(indexNumber, str);
thirdinoryNumber++;
System.out.println(indexNumber);
thirdinoryNumber++;
}
else
{
//We have used number from 0-9. Time to start replacing letters
if(currentlyActiveSimpleLetter2<simpleLetters.length)
{
if(currentlyActiveSimpleLetter2==0) //If this is the 'first' time we reach this point, reset the number counter.
{
thirdinoryNumber = 0;
}
if(thirdinoryNumber<10)
{
indexNumber = simpleLetters[currentlyActiveSimpleLetter2]+symbols[currentlyActiveSymbol]+thirdinoryNumber;
wordMap.put(indexNumber, str);
thirdinoryNumber++;
System.out.println(indexNumber);
}
else
{
thirdinoryNumber = 0;
currentlyActiveSimpleLetter2++; //If we are at the peek of usable numbers (0-9) reset simpleletter array position to
// 0 and numbercounter to 0
}
}
else
{
//We have used number from 0-9. Time to start replacing symbols
if(currentlyActiveSymbol2<symbols.length)
{
if(currentlyActiveSymbol2==0) //If this is the 'first' time we reach this point, reset the number counter.
{
thirdinoryNumber = 0;
}
if(thirdinoryNumber<10)
{
indexNumber = simpleLetters[currentlyActiveSimpleLetter2]+symbols[currentlyActiveSymbol]+thirdinoryNumber;
wordMap.put(indexNumber, str);
thirdinoryNumber++;
System.out.println(indexNumber);
}
else
{
thirdinoryNumber = 0;
currentlyActiveSymbol2++; //If we are at the peek of usable numbers (0-9) reset symbol array position to
// 0 and numbercounter to 0
}
}
}
}
}
}
}
else
{
System.out.println("Error in Somewhere. Length Exceeded");
}
}
}
br.close();
System.out.println("Completed");
System.out.println(wordMap.get(0));
}
catch(Exception e)
{
e.printStackTrace();
}
finally
{
try
{
br.close();
}
catch(Exception e)
{
e.printStackTrace();
}
}
return wordMap;
}
}
Unfortunately this doesn't work. It prints the results, and it is bunch of !0 after the result 'z99'. Below is a small piece of it:
!0
!0
!0
!0
...
Completed
null
Apart from that, after k99, it has generated ids from 10-199 then started back with m0 properly. You can find the result file from here.
As you can see, wordMap.get(0) also generated null. What is wrong here? If there is any other simple method for generating 75000 unique ids with maximum 3 digits/letters/symbols length, I am more than happy to move with it.
Here is generator with enough IDs.
public class Main {
private char[] A;
void init()
{
A = new char[] {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
};
System.out.println("digits = " + A.length);
//for (int i = 0; i < A.length; i++)
// System.out.print(A[i] + " ");
//System.out.println();
}
public void generate(int length, String id)
{
if (length == 3) {
System.out.println(id);
} else {
for (int i = 0; i < A.length; i++)
generate(length + 1, id + A[i]);
}
}
public static void main(String[] args) {
Main test = new Main();
test.init();
test.generate(0, "");
}
}
The number of unique IDs is (26 + 26 + 10) ^ 3 = 62^3 = 238328.
Obviously you need to adapt it to fit your particular problem.
Actually only 43 characters are needed since 43 ^ 3 = 79507 > 75200.
EDIT: Explanation of the generate() method.
This method implements a recursive algorithm to generate combinations of characters (the keys). The meaning of the parameters is the following:
length The length of the key.
id stores the combination of characters.
The following picture can help to understand the algorithm.
This is similar to how the decimal (or any other base) numbers are formed.
A thing that I don't noticed is that you are trying to first create all the possible keys of length 1, then all possible keys of length 2, and so on. My generator creates keys of exactly 3 character only. That behavior can be achieved modifying the generate() method as follows:
public void generate(int count, String id)
{
if (count == 0) {
System.out.println(id);
} else {
for (int i = 0; i < A.length; i++)
generate(count - 1, id + A[i]);
}
}
And then call the method tree times:
test.generate(1, "");
test.generate(2, "");
test.generate(3, "");
Some keys contains leading zeros but that shouldn't be a problem since this keys are identifiers, not numbers. The number of possible keys increases by length(alphabet) + length(alphabet) ^ 2, i.e. we have 62 + 62^2 additional keys.
Since the length of the key is at most 3 the iterative version can be easily implemented using for loops:
public void iterative_generator()
{
for (int i = 0; i < A.length; i++) {
for (int j = 0; j < A.length; j++) {
for (int k = 0; k < A.length; k++) {
System.out.println("" + A[i] + A[j] + A[k]);
}
}
}
}
I think you get the idea.
You could create a method that basically converts a decimal number to a base of your choice. Here I have 46 symbols for example, which gives 97336 unique sequences:
private static final String[] symbols = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h",
"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "!", "#", "#", "$", "%", "^", "&",
"*", "~", "?" };
public static String getSequence(final int i) {
return symbols[i / (symbols.length * symbols.length)] + symbols[(i / symbols.length) % symbols.length]
+ symbols[i % symbols.length];
}
(Posted on behalf of the question author).
This is how I wrote my code according to the answer of Stack Overflow user "Keppil".
import java.io.*;
import java.util.*;
public class HashCreator
{
private Map completedWordMap;
private String[]simpleLetters = {"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"};
private char[] A;
private static final String[] symbols = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f", "g", "h",
"i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "!", "#", "#", "$", "%", "^", "&",
"*", "~", "?" };
public HashCreator()
{
for(int i=0;i<75001;i++)
{
System.out.println(getSequence(i));
}
}
public static String getSequence(final int i) {
return symbols[i / (symbols.length * symbols.length)] + symbols[(i / symbols.length) % symbols.length]
+ symbols[i % symbols.length];
}
}
Related
This code takes an input string from the user, which may contain special characters. We then output the letters that are missing from the alphabet. For example, "the quick brown fox jumped over the lazy dog" would have an empty string returned, but "ZYXW, vu TSR Ponm lkj ihgfd CBA." would be missing the letters "eq".
Currently, my program is returning the whole alphabet instead of only the missing characters.
import java.io.*;
import org.apache.commons.lang3.*;
public class QuickBrownFox {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = reader.readLine();
s = s.toUpperCase();
String[] arr = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S",
"T", "U", "V", "W", "X", "Y", "Z" };
String chars_only = "";
for (int i = 0; i < s.length(); i++) {
for (int j = 0; j < arr.length; j++) {
if (s.substring(i, i + 1).equals(arr[j])) {
chars_only += s.substring(i, i + 1);
}
}
}
System.out.println(chars_only); // now we have a string of only alphabet letters
String missing = "";
for (int j = 0; j < arr.length; j++) {
if (StringUtils.contains(arr[j], chars_only) == false) { // alphabet letter not found
missing += arr[j];
}
}
missing = missing.toLowerCase();
System.out.println("missing letters: " + missing);
}
}
StringUtils.contains(arr[j], chars_only) checks whether the alphabet letter (arr[j]) contains the whole string chars_only which will never be the case (unless you enter just one character). What you want is !chars_only.contains(arr[j]) (no need to use StringUtils.contains). This will check whether the inputted letters do not contain the jth alphabet letter. Alternatively you can keep StringUtils.contains, just swap the parameters: !StringUtils.contains(chars_only, arr[j]).
Btw, you could use streams to reduce the amount of code:
import java.util.Arrays;
import java.util.List;
import java.io.*;
import java.util.stream.Collectors;
public class QuickBrownFox {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String s = reader.readLine().toUpperCase();
List<String> alphabet = Arrays.asList("A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S",
"T", "U", "V", "W", "X", "Y", "Z");
String missing = alphabet.stream()
.filter(letter -> !s.contains(letter))
.collect(Collectors.joining())
.toLowerCase();
System.out.println("missing letters: " + missing);
}
}
One option is to use a Set initialized with given alphabet-chars. Then remove from set any chars contained in input-string. Remainder will reflect missing chars.
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
public class TestAlphabet {
public static void main(String[] args) {
Set<Character> set = new HashSet<Character>();
Character[] arr = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S',
'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
Collections.addAll(set, arr);
String s1="abc";
System.out.println("input:"+s1);
new TestAlphabet().new Missing().getMissing(set, s1).forEach(System.out::print);
System.out.println("\n");
String s2="the quick brown fox jumped over the lazy dog";
System.out.println("input:"+s2);
new TestAlphabet().new Missing().getMissing(set, s2).forEach(System.out::print);
System.out.println("\n");
String s3="ZYXW, vu TSR Ponm lkj ihgfd CBA.";
System.out.println("input:"+s3);
new TestAlphabet().new Missing().getMissing(set, s3).forEach(System.out::print);
}
class Missing
{
public Set<Character> getMissing(Set<Character> orig, String s)
{
//keep origin
Set<Character> set = new HashSet<Character>();
set.addAll(orig);
s=s.toUpperCase();
for(int i=0;i<s.length();i++)
{
Character c=s.charAt(i);
set.remove(c);
}
return set;
}
}
}
Output
input:abc
DEFGHIJKLMNOPQRSTUVWXYZ
input:the quick brown fox jumped over the lazy dog
S
input:ZYXW, vu TSR Ponm lkj ihgfd CBA.
EQ
I have below ArrayList
["P", "a", "y", "P", "a", "l", "I", "n", "d", "i", "a"]
Expected result [y, l, I, n, d, i]
I want to remove all duplicates, including original value.
For example: 'P' is duplicate. If i use set, it will remove duplicates and one 'P' will display.
i want to remove all the 'P'.
I have tried below code. But its validating only if there is even set of chars,
ArrayList<Character> unique = new ArrayList<Character>();
for (Character c : b) {
if (unique.contains(c)) {
unique.remove(c);
} else {
unique.add(c);
}
}
This code validates and removing 'P', but not 'a'. Because 'a' listed 3 t
First it count occurence of every char then filter out by number of occurrence (only with one occurence).
List<Character> input = Arrays.asList('P', 'a', 'y', 'P', 'a', 'l', 'I', 'n', 'd', 'i', 'a');
List<Character> collect = input.stream()
.collect(Collectors.groupingBy(p -> p, Collectors.counting()))
.entrySet().stream()
.filter(e -> e.getValue() == 1)
.map(Map.Entry::getKey)
.collect(Collectors.toList());
System.out.println(collect);
The older version without streams can be written like that:
// create Map with count occurence
Map<Character, Integer> countMap = new HashMap<>();
for (Character value : input) {
if (!countMap.containsKey(value)) {
countMap.put(value, 1);
} else {
countMap.put(value, countMap.get(value) + 1);
}
}
// filter Map
List<Character> collect = new ArrayList<>();
for (Map.Entry<Character, Integer> value : countMap.entrySet()) {
if( value.getValue() == 1) {
collect.add(value.getKey());
}
}
System.out.println(collect);
Try this approach:
public static void main(String[] args) {
List<Character> unique = Arrays.asList('P', 'a', 'y', 'P', 'a', 'l', 'I', 'n', 'd', 'i', 'a');
List<Character> result = unique.stream().filter(i1 -> unique.stream().filter(i2 -> i1.equals(i2)).count() == 1).collect(Collectors.toList());
System.out.println(result);
}
Output is: [y, l, I, n, d, i]
This may help
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
public class RemoveDuplicates {
public static void main(String[] args) {
String string = "PayPalIndia";
List<Character> strings = string.chars().mapToObj(c -> (char) c).collect(Collectors.toList());
Set<Character> set = new HashSet<>();
Iterator<Character> iterator = strings.iterator();
Set<Character> invalid = new HashSet<>();
while (iterator.hasNext()) {
Character c = iterator.next();
if (set.contains(c)) {
iterator.remove();
invalid.add(c);
} else {
set.add(c);
}
}
System.out.println("Duplicate parents");
invalid.forEach(System.out::print);
System.out.println();
strings.removeAll(invalid);
System.out.println("=============");
System.out.println("After removing Duplicates...");
strings.forEach(System.out::print);
System.out.println();
}
}
A fun way you can do this without Java 8 streams is to make an int array of size 128 that will hold the counts of each occurrence at the index of the character value.
For example, if a appears 3 times, array[97] will equal 3, where 97 is the Ascii value of a (I know technically ascii is not used).
The downside to this implementation is it cannot handle any other characters above the first 128 characters in the ascii table. Though you can extend it accordingly.
Here is what this would look like:
public static void main(String[] args) {
ArrayList<Character> list = new ArrayList<>();
list.add(Character.valueOf('P'));
list.add(Character.valueOf('t'));
list.add(Character.valueOf('L'));
list.add(Character.valueOf('L'));
list.add(Character.valueOf('b'));
list.add(Character.valueOf('P'));
list.add(Character.valueOf('c'));
int [] lookup = new int[128];
//Build the lookup table
for (char c : list) {
lookup[c]++;
}
//Remove the values that are greater than 1 in the lookup table
for (int j = 0; j < lookup.length; j++) {
int count = lookup[j];
for (int k = 0; k < count && count > 1; k++) {
list.remove(Character.valueOf((char) j));
}
}
}
The code basically breaks down to two main parts:
Building the lookup table.
Removing values from the list using the lookup table as reference.
Now this is obviously more complicated than a solution with Map, Set, or using streams would be, but I figured with your requirements you may not be able to use stream either.
Try this
ArrayList charsList = new ArrayList<>(Arrays.asList('P', 'a', 'y', 'P', 'a', 'l', 'I', 'n', 'd', 'i', 'a'));
List listWithoutDuplicates = charsList.stream().distinct().collect(Collectors.toList());
This question already has answers here:
Java recursion phone number letters
(5 answers)
Closed 7 years ago.
I know this question has been asked a hundred times but I am looking for a solution that does not involve any String functions or external classes.
I have written a few classes that actually work but they all use String.substring or String.replace, Arraylists etc. which is not allowed in my situation.
I have been on this for more than a week now and I can't seem to get any progress.
I just can't put String methods in a very big loop or something.
Any ideas?
Here is what I have written up until now.
public class Oldie {
public static void main(String[] args) {
char[][] array = {
{ '0' }, { '1' }, { 'A', 'B', 'C' }, { 'D', 'E', 'F' },
{ 'G', 'H', 'I' }, { 'J', 'K', 'L' }, { 'M', 'N', 'O' },
{ 'P', 'Q', 'R', 'S' }, { 'T', 'U', 'V' }, { 'W', 'X', 'Y', 'Z' }
};
String num = "222";
int[] number = new int[num.length()];
char[] permutations = new char[num.length()];
for (int i = 0; i < num.length(); i++) {
number[i] = Character.getNumericValue(num.charAt(i));
}
char First, Second, Third;
for (char i = array[number[0]][0]; i <= array[number[0]][array[number[0]].length - 1]; i++) {
First = i;
for (char j = array[number[1]][0]; j <= array[number[1]][array[number[1]].length - 1]; j++) {
Second = j;
for (char k = array[number[2]][0]; k <= array[number[2]][array[number[2]].length - 1]; k++) {
Third = k;
System.out.println("" + First + "" + Second + "" + Third);
}
}
}
}
}
It would be better if I could do it in a base type solution with redix etc.
I am not quite sure, what you mean with your loops, but when you fix it, this should be another solution without saving the String (right now this throws an "java.lang.ArrayIndexOutOfBoundsException" since i dont right understand, what you want to accomplish with your for-loops). This code should be more considered as an hint how to solve your problem and not the full solution! This also kind of saves old Strings. Instead you could also delete the last char of the String at the end of each for-loop:
public class Oldie {
char[][] array = {
{ '0' }, { '1' }, { 'A', 'B', 'C' }, { 'D', 'E', 'F' },
{ 'G', 'H', 'I' }, { 'J', 'K', 'L' }, { 'M', 'N', 'O' },
{ 'P', 'Q', 'R', 'S' }, { 'T', 'U', 'V' }, { 'W', 'X', 'Y', 'Z' }
};
String num = "222";
String savedPerm;
int[] number = new int[num.length()];
public static void main(String[] args) {
Oldie oldie = new Oldie();
oldie.givePerm(0);
}
Oldie(){
for (int i = 0; i < num.length(); i++) {
number[i] = Character.getNumericValue(num.charAt(i));
}
}
private void givePerm(int position){
String oldSavedPerm=savedPerm;
// if(array.length!=number.length){
// System.out.println("Different length!");
// System.out.println(array.length+";"+number.length);
// return;
// }
for (char c = array[number[position]][0]; c <= array[number[position]][array[number[position]].length - 1]; c++) {
savedPerm=c+oldSavedPerm;
if(position<array.length-1)
givePerm(position+1);
else
System.out.println(savedPerm);
}
}
}
Here is my approach on your problem.
char[][] array = {
{ '0' }, { '1' }, { 'A', 'B', 'C' }, { 'D', 'E', 'F' },
{ 'G', 'H', 'I' }, { 'J', 'K', 'L' }, { 'M', 'N', 'O' },
{ 'P', 'Q', 'R', 'S' }, { 'T', 'U', 'V' }, { 'W', 'X', 'Y', 'Z' }
};
String num = "123";
// creates an combination Array
// for 123 this is {{1},{ABC},{DEF}}
char[][] combinationArr = new char[num.length()][];
for(int ix = 0; ix < num.length(); ix++)
combinationArr[ix] = array[Character.getNumericValue(num.charAt(ix))];
// now print all permutations of combination Array
// ics holds the actual index at each position
int[] ics = new int[num.length()];
boolean end = false;
while(!end){ // while there are combinations left
// print the actual combination
for(int i = 0; i < combinationArr.length; i++)
System.out.print(combinationArr[i][ics[i]]);
System.out.println();
// increases one index, starting with the last one.
// If there is no char left it starts again at 0
// and the index before will get increased.
// If the first one could not get increased
// we have all combinations.
for(int i = ics.length - 1; i >= 0; i--){
ics[i]++;
if(ics[i] == combinationArr[i].length)
if(i == 0) end = true;
else ics[i] = 0;
else break;
}
}
Here is what actually worked for me!! Thanks to ctst!
public class Oldie {
private static char[][] array = { { '0' }, { '1' }, { 'A', 'B', 'C' }, { 'D', 'E', 'F' },
{ 'G', 'H', 'I' }, { 'J', 'K', 'L' }, { 'M', 'N', 'O' },
{ 'P', 'Q', 'R', 'S' }, { 'T', 'U', 'V' }, { 'W', 'X', 'Y', 'Z' } };
private static String num = "2222";
private static char[] savedPerm = new char[num.length];
private static int[] number = new int[num.length()];
public static void main(String[] args) {
for (int i = 0; i < num.length(); i++) {
number[i] = Character.getNumericValue(num.charAt(i));
}
givePerm(0);
}
private static void givePerm(int position) {
for (char c = array[number[position]][0]; c <= array[number[position]][array[number[position]].length - 1]; c++) {
savedPerm[position] = c;
if (position < number.length - 1)
givePerm(position + 1);
else{
for(char text: savedPerm){
System.out.print(""+text);
}
System.out.println();
}
}
}
}
I would suggest you to make a recursive method:
private String givePerm(String givenPerm, char[][] array, int position, int[] number){
if(array.length!=number.length)
return null;
for (char c = array[number[position]][0]; c <= array[number[position]][array[number[position]].length - 1]; c++) {
String permString;
if(position<array.length-1)
permString = givePerm(c+givenPerm, array, position+1);
else
permString = ""+c;
return permString;
}
}
Using recursion, you can call the permutations method and keep on reducing the the number of input digits, by grabbing the head digit and passing the tail into the next call.
public class Oldie {
private static final char[][] KEYS = {
{ '0' },
{ '1' }, { 'A','B','C' }, { 'D','E','F' },
{ 'G','H','I' }, { 'J','K','L' }, { 'M','N','O' },
{ 'P','Q','R','S' }, { 'T','U','V' }, { 'W','X','Y','Z' }
};
public static void main(String[] args) {
try {
permutations("222");
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
public static void permutations(String inputNumber) throws IllegalArgumentException {
permutations(toDigitArray(inputNumber), "");
}
private static void permutations(int[] inputDigits, String outputLetters) throws IllegalArgumentException {
int headDigit = inputDigits[0];
int[] tailDigits = tail(inputDigits);
char[] letters = KEYS[headDigit];
for (int i = 0; i < letters.length; i++) {
char letter = letters[i];
String result = outputLetters + letter;
if (tailDigits.length == 0) {
System.out.println(result);
} else {
permutations(tailDigits, result);
}
}
}
private static int[] toDigitArray(String str) throws IllegalArgumentException {
return toDigitArray(str.toCharArray());
}
private static int[] toDigitArray(char[] arr) throws IllegalArgumentException {
int[] intArr = new int[arr.length];
for (int i = 0; i < intArr.length; i++) {
if (!Character.isDigit(arr[i])) {
throw new IllegalArgumentException("Character is not a valid digit");
}
intArr[i] = Character.digit(arr[i], 10);
}
return intArr;
}
private static int[] tail(int[] arr) {
int[] dest = new int[arr.length - 1];
System.arraycopy(arr, 1, dest, 0, dest.length);
return dest;
}
}
Output
AAA
AAB
AAC
ABA
ABB
ABC
ACA
ACB
ACC
BAA
BAB
BAC
BBA
BBB
BBC
BCA
BCB
BCC
CAA
CAB
CAC
CBA
CBB
CBC
CCA
CCB
CCC
how to delete specified character in array and copy the elements of the first array to the second array ?
i tried to convert the array to a list to be able to check if the array contain this specified character, then i tried to remove this character and create another array by copying the element of the first array but without the specified character.
the system display this error:
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.AbstractList.remove(AbstractList.java:161)
at java.util.AbstractList$Itr.remove(AbstractList.java:375)
at java.util.AbstractCollection.remove(AbstractCollection.java:269)
at test4.test4.main(Question4.java:21)
this is my code:
package test4;
import java.util.Arrays;
public class test4 {
public static void main(String[] args) {
String[] a = new String[]{ "A", "b", "C", "$", "$", "$", "d", "s", "w", "t", "Z",
"r", "I", "o", "A", "b", "C", "$", "$", "$", "d", "s", "w", "t" };
String[] b = new String[a.length];
int num = 0;
for(int i =0; i<a.length; i++){
if(Character.isUpperCase(i)){
num++;
}
if(Arrays.asList(a).contains("$")){
Arrays.asList(a).remove("$");
b[i] =a[i];
}
}
System.out.println("number os uperCase is: " + num);
System.out.println();
System.out.println("this is the new Array: " + Arrays.toString(b));
}
}
can anyone help me to fix this problem??
Arrays.asList(a) returns a list of fixed length, so Arrays.asList(a).remove("$"); can't work.
You can iterate over the array instead :
int count = 0;
for(int i =0; i<a.length; i++){
if(Character.isUpperCase(a[i].charAt(0))){
num++;
}
if(!a[i].equals("$")){ // copy only non "$" Strings to the output array
b[count] =a[i];
count++;
}
}
Note that your count of upper case characters was also wrong, since you were calling Character.isUpperCase on indices of the array instead of the characters contained in it.
Another thing you should consider is changing String[] a to char[] a, since it looks like you only have single character Strings in that array.
I'm REALLY new at Java and this is the first Question I've answered, so I'm sorry if I'm wrong. Here it goes:
Character.isUpperCase() can not check against a String. It can only check against a char. So I would change the array from a String to char (' instead of " for each character).
Second, the if statement needs to check a[i] not just i.
Third, I would make your second array an ArrayList and convert each char to be added toString so that the size of the second array wouldn't matter and can be used with different arrays.
import java.util.ArrayList;
import java.util.Arrays;
public class test4 {
public static void main(String[] args) {
char[] a = new char[]{ 'A', 'b', 'C', '$', '$', '$', 'd', 's', 'w', 't', 'Z',
'r', 'I', 'o', 'A', 'b', 'C', '$', '$', '$', 'd', 's', 'w', 't' };
ArrayList<String> b = new ArrayList<>();
int num = 0;
for(int i = 0; i<a.length; i++){
if(Character.isUpperCase(a[i])){
num++;
}
if(Arrays.asList(a[i]).contains('$')){
}
else{
String conv = Character.toString(a[i]);
b.add(conv);
}
}
System.out.println("number of upperCase is: " + num);
System.out.println();
System.out.print("This is the new Array: " );
for(String value: b ){
System.out.print(value + " ");
}
}
}
Here is my code. I am having an issue. It works just fine but when you convert morse code to english, it only prints out the morse code single digit letters. Can someone give me a solution or at least help me understand what is wrong because it is immensely frustrating.
Here is the bit of my code that matters
An example of the problem is when i put in .- it printed e and t, not a.
public class Project1
{
public static void main( String [] args )
{
System.out.println();
choice();
}
public static void choice()
{
int user_choice = 0;
user_choice = Input.getInt("Enter 1 if you want to change English to Morse code, and enter 2 to change Morse code to English");
if(user_choice == 1)
{
String output = new String();
String inital = new String();
inital = english_to_morse();
for( int k = 0; k < inital.length(); k++)
{
output += morse(inital.charAt( k ));
}
System.out.print(output);
}
if(user_choice == 2)
{
String output2 = new String();
String inital2 = new String();
inital2 = morse_to_english();
for( int k = 0; k < inital2.length(); k++)
{
System.out.println("#####"+String.valueOf(inital2.charAt( k ))+"#####");
output2 += english(String.valueOf(inital2.charAt( k )));
}
System.out.print(output2);
}
}
public static String english_to_morse()
{
String user_input = new String();
user_input = Input.getString("Enter a phrase and I'll convert it to Morse Code");
return user_input.toLowerCase();
}
public static String morse_to_english()
{
String user_input = new String();
user_input = Input.getString("Enter a phrase in Morse Code and I'll convert it to English");
return user_input.toLowerCase();
}
public static String morse(char letter)
{
String output = new String();
char[] alphabet_numbers = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ' ' };
String morse_code[] = { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", "|" };
for( int j = 0; j < alphabet_numbers.length; j++ )
{
if (alphabet_numbers[j]==letter)
{
output = morse_code[j];
}
}
return output + " ";
}
public static String english(String letter)
{
String output = new String();
String alphabet_numbers[] = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", " " };
String morse_code[] = { ".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--..", "-----", ".----", "..---", "...--", "....-", ".....", "-....", "--...", "---..", "----.", "|" };
for( int j = 0; j < morse_code.length; j++ )
{
if (morse_code[j].equals(letter))
{
output = alphabet_numbers[j];
}
}
return output + " ";
}
}
Well the reason why .- is giving et instead of a is due to the way you're reading the string.
Your code reads . and then looks up the table to determine whether it corresponds to any alpha character, in which case it does: e. Then you read a - and you look it up and you get a t.
If your input is literally just
.-.---.-.-.........-----.-.-.-.-
You're pretty much stuck because you don't know when one ends and another begins. As another example, how should one distinguish between the following strings
.
..
...
....
They are all equally valid signals, but depending on how you interpret it, you get very different results.
You can't say something like "I'll just take the longest matching string" because there is no reason why that is a valid rule.
If the sample input I provided above does not match your input, you should indicate what your input is.
The problem is in how you iterate your strings.
When going from English to Morse, it is ok to just iterate single characters as you do here:
for( int k = 0; k < inital.length(); k++) {
output += morse(inital.charAt( k ));
}
but when going from Morse to English you have to iterate several characters at once, because a symbol in Morse generally spans several characters. For instance, the Morse string .- -... -.-. has three symbols that correspond to abc in English, but they have 2, 4 and 4 characters each.
So when iterating your Morse string, you have to split it by spaces, and iterate each of the substrings. In the case above, you'll iterate .-, then -... and then -.-.:
for(String symbol : inital2.split(" ")){
output2 += english(symbol);
}
Your problem is this line
output2 += english(String.valueOf(inital2.charAt( k )));
You give ".-" as input, but it does not convert ".-", because it takes each character of the string ".-" and converts it, which gives your "e t" result.
To fix this you have to use a separator in your morse code input. You already somehow defined " " as a separator so I will use it.
if(user_choice == 2){
String output2 = new String();
String[] inital2 = morse_to_english().split(" ");
for( int k = 0; k < inital2.length; k++){
output2 += english(inital2[k]);
}
System.out.print(output2);
}