I'm trying to replace W by OU only if the char before him is at position 0 of the string and if it's a consonnant and only the first W in the String, ie TWITWIC --> TOUITWIC.
Here is my code (tampon is the input i give to the code into my test):
public class Phonkw {
static Map<String, String> consonnantReplace = new HashMap<String, String>();
static {
consonnantReplace.put("BW", "BOU");
consonnantReplace.put("CW", "COU");
consonnantReplace.put("DW", "DOU");
consonnantReplace.put("FW", "FOU");
consonnantReplace.put("GW","GOU");
consonnantReplace.put("HW","HOU");
consonnantReplace.put("JW", "JOU");
consonnantReplace.put("KW", "KOU");
consonnantReplace.put("LW", "LOU");
consonnantReplace.put("MW", "MOU");
consonnantReplace.put("NW", "NOU");
consonnantReplace.put("PW", "POU");
consonnantReplace.put("QW", "QOU");
consonnantReplace.put("RW", "ROU");
consonnantReplace.put("SW", "SOU");
consonnantReplace.put("TW", "TOU");
consonnantReplace.put("VW","VOU");
consonnantReplace.put("WW", "WOU");
consonnantReplace.put("XW","XOU");
consonnantReplace.put("ZW", "ZOU");
}
public static String phonkw1(final String tampon){
if (tampon==null){
return "";
}
if(consonnantReplace.containsKey(tampon)){
return consonnantReplace.get(tampon);
}
return tampon;
}
}
I think i need to substring tampon at (0,1) but i cant get the value in map byt the substring.
EDIT : RESOLVE.
In case you want to stick to your Map solution, you will indeed need to use substring(). For the lookup, you want to go for substring(0, 2) because that will be the first two characters of the String tampon. However, be aware that this will throw StringIndexOutOfBoundsException in case of single-letter-words, so a guard checking the length would be required.
This is your code modified accordingly:
import java.util.*;
public class Phonkw {
static Map<String, String> consonnantReplace = new HashMap<String, String>();
static {
consonnantReplace.put("BW", "BOU");
consonnantReplace.put("CW", "COU");
consonnantReplace.put("DW", "DOU");
consonnantReplace.put("FW", "FOU");
consonnantReplace.put("GW","GOU");
consonnantReplace.put("HW","HOU");
consonnantReplace.put("JW", "JOU");
consonnantReplace.put("KW", "KOU");
consonnantReplace.put("LW", "LOU");
consonnantReplace.put("MW", "MOU");
consonnantReplace.put("NW", "NOU");
consonnantReplace.put("PW", "POU");
consonnantReplace.put("QW", "QOU");
consonnantReplace.put("RW", "ROU");
consonnantReplace.put("SW", "SOU");
consonnantReplace.put("TW", "TOU");
consonnantReplace.put("VW","VOU");
consonnantReplace.put("WW", "WOU");
consonnantReplace.put("XW","XOU");
consonnantReplace.put("ZW", "ZOU");
}
public static String phonkw1(final String tampon){
if (tampon == null){
return "";
}
if (tampon.length() >= 2) {
final String key = tampon.substring(0, 2);
if (consonnantReplace.containsKey(key)) {
return consonnantReplace.get(key) + tampon.substring(2);
}
}
return tampon;
}
public static void main(final String... args) {
for (final String arg : args)
System.out.println(phonkw1(arg));
}
}
You could actually create your Map<String, String> with a loop. If you do not intend to modify the Map during runtime, you can also wrap it with Collections.unmodifiableMap() to prevent it from accidental modification.
And you might fix the spelling mistake, it's consonant, not consonnant.
The code would then look like this:
import java.util.*;
public class Phonkw {
private static final Map<String, String> consonantReplace = createConsonantReplaceMap();
private static Map<String, String> createConsonantReplaceMap() {
final Map<String, String> map = new HashMap<>();
final String consonants = "BCDFGHJKLMNPQRSTVWXZ";
for (final char consonant : consonants.toCharArray())
map.put(consonant + "W", consonant + "OU");
return Collections.unmodifiableMap(map);
}
public static String phonkw1(final String tampon) {
if (tampon == null) return "";
if (tampon.length() < 2) return tampon;
final String key = tampon.substring(0, 2);
if (consonantReplace.containsKey(key))
return consonantReplace.get(key) + tampon.substring(2);
return tampon;
}
public static void main(final String... args) {
for (final String arg : args)
System.out.println(phonkw1(arg));
}
}
You don't really need a Map if all the entries are uniform replacements. In that case you could directly check, like this:
public class Phonkw {
private static final String CONSONANTS = "BCDFGHJKLMNPQRSTVWXZ";
public static boolean isConsonant(final char c) {
return CONSONANTS.indexOf(c) != -1;
}
public static String phonkw1(final String tampon) {
if (tampon == null) return "";
if (tampon.length() < 2) return tampon;
if (tampon.charAt(1) == 'W' && isConsonant(tampon.charAt(0)))
return tampon.charAt(0) + "OU" + tampon.substring(2);
return tampon;
}
public static void main(final String... args) {
for (final String arg : args)
System.out.println(phonkw1(arg));
}
}
With a regular expression, the code could be even simpler:
public class Phonkw {
public static String phonkw1(final String tampon) {
return tampon == null ? "" : tampon.replaceAll("^([BCDFGHJKLMNPQRSTVWXZ])W", "$1OU");
}
public static void main(final String... args) {
for (final String arg : args)
System.out.println(phonkw1(arg));
}
}
The code below should replace anything before 'W' that is a consonant but only if that consonant is at position 0 in the string.
public class Phonkw {
static Map<String, String> consonnantReplace = new HashMap<String, String>();
static {
consonnantReplace.put("BW", "BOU");
consonnantReplace.put("CW", "COU");
consonnantReplace.put("DW", "DOU");
consonnantReplace.put("FW", "FOU");
consonnantReplace.put("GW", "GOU");
consonnantReplace.put("HW", "HOU");
consonnantReplace.put("JW", "JOU");
consonnantReplace.put("KW", "KOU");
consonnantReplace.put("LW", "LOU");
consonnantReplace.put("MW", "MOU");
consonnantReplace.put("NW", "NOU");
consonnantReplace.put("PW", "POU");
consonnantReplace.put("QW", "QOU");
consonnantReplace.put("RW", "ROU");
consonnantReplace.put("SW", "SOU");
consonnantReplace.put("TW", "TOU");
consonnantReplace.put("VW", "VOU");
consonnantReplace.put("WW", "WOU");
consonnantReplace.put("XW", "XOU");
consonnantReplace.put("ZW", "ZOU");
}
public static String phonkw1(String tampon) {
if (tampon == null) {
return "";
}
Iterator<String> it = consonnantReplace.keySet().iterator();
while (it.hasNext()) {
String s = it.next();
if (tampon.indexOf(s) == 0) {
tampon = tampon.replace(s, consonnantReplace.get(s));
}
}
return tampon;
}
}
A regex might be another solution?
You should use a regular expression to solve this issue, check in the comments for a good regex to use
If you want to use a non-regex solution you could consider the following code. You can indeed use a String.substring, or use String.charAt for a single character
public class Phonkw {
public static String phonkw1(final String tampon){
if (tampon==null){
return "";
}
if (tampon.length() > 1 && isConsonant(tampon.charAt(0)) {//the first character is a consonant
if (tampon.charAt(1) == 'W') {//the 2nd character is a W
return tampon.charAt(0) + "OU" + tampon.substring(2); // not an optimal solution..
}
}
return tampon;
}
public static boolean isConsonant(char c) {
return "BCDFGHJKLMNPQRSTVWXZ".indexOf(c) != -1;
}
}
Related
I want print single variable, array and maybe double array,
I use following code, add a type when I need it,
but ... as you see ... it works but not smart.
So, question is "Is there a smart way to print Arrays?"
import java.util.Arrays;
class Rec{
int val;
public String toString(){
return "" + val;
}
Rec(int val){this.val=val;}
}
public class Main
{
public static void main(String[] args) {
Rec r = new Rec(0);
Boolean[] ba = new Boolean[]{true, false, true, true};
Rec[] ra = new Rec[]{new Rec(1), new Rec(2), new Rec(3)};
int[][] iaa = new int[][]{{1,2,3}, {3,4,5}};
System.out.printf("r=%s ba=%s ra=%s iaa=%s \n", s(r), s(ba), s(ra), s(iaa));
}
static <T> String s(T n) {
if(n instanceof int[]){
return Arrays.toString((int[])n);
}else if(n instanceof int[][]){
return Arrays.deepToString((int[][])n);
}else if(n instanceof boolean[]){
return Arrays.toString((boolean[])n);
}else if(n instanceof boolean[][]){
return Arrays.deepToString((boolean[][])n);
}else if(n instanceof Boolean[]){
return Arrays.toString((Boolean[])n);
}else if(n instanceof Rec[]){
return Arrays.toString((Rec[])n);
//}else if(n instanceof T[]){ // error: illegal generic type for instanceof
// return Arrays.toString((T[])n);
}else{
return "" + n;
}
}
}
If you really want to customize your printing for variable arrays then why not do the following:
public static String s(Object s) {
return s.toString();
}
public static String s(Object[] s) {
return Arrays.toString(s);
}
public static String s(Object[][] s) {
return Arrays.deepToString(s);
}
// For each primitive type of your single or multi dimension
// declare the following for either single or multi dimensional
public static String s(int[][] s) {
return Arrays.deepToString(s);
}
public static String s(int[] s) {
return Arrays.toString(s);
}
But keep in mind you are basically repackaging what the API already does.
I'm trying to write the best algorithm to solve the problem. Can a given String be formed with a given array of String?
I've tried multiple solutions but the execution time exceed my requirements.
import java.util.ArrayList;
import java.util.Scanner;
public class JavaApplication5 {
static boolean encontrado;
static ArrayList<String> tp=new ArrayList<>();
static ArrayList<String> ts=new ArrayList<>();
public static void main(String[] args) {
tp.add("H");
tp.add("B");
ts.add("HE");
ts.add("LI");
Scanner t=new Scanner(System.in);
while(t.hasNext()){
encontrado=false;
String f=t.nextLine().replaceAll(" ","").toUpperCase();
if(calcular(f,0)){
System.out.println(YES");
}else{
System.out.println("NO");
}
}
}
private static boolean calcular(String f,int pos) {
if(f.length()>pos&&!encontrado){
if(tp.indexOf(String.valueOf(f.charAt(pos)))!=-1){
if(pos==f.length()-1){
encontrado=true;
}else{
calcular(f,pos+1);
}
}
}
if(f.length()>pos+1&&!encontrado){
if(ts.indexOf(String.valueOf(f.charAt(pos))+String.valueOf(f.charAt(pos+1)))!=-1){
if(pos+1==f.length()-1){
encontrado=true;
}else{
calcular(f,pos+2);
}
}
}
return encontrado;
}
}
Expectations
arrayString={"A","B","CD"}
A.s="ACDBB"-->POSSIBLE
B.s="DCAAB"-->NOT POSSIBLE
Try something like this:
public class Test {
static String[] arrayString = new String[] {"A","B","CD"};
static boolean possible(String str) {
if (str.length() == 0) {
return true;
}
for (String component : arrayString) {
if (str.startsWith(component)) {
String shorterStr = str.substring(component.length());
if (possible(shorterStr)) {
return true;
}
}
}
return false;
}
static void test(String str) {
String result = (possible(str) ? "" : "NOT ") + "POSSIBLE";
System.out.println(str + " -> " + result);
}
public static void main(String[] args) {
test("ACDBB");
test("DCAAB");
}
}
I have simple problem, but I'm not able to fix it. I have this interface...
public interface KeyInput extends Input {
public static final int TEST1 = 0x01;
public static final int TEST2 = 0x02;
}
...this string variable...
String inputString = "TEST1";
...and this method.
public void doSomething(int _input) {
}
I want to parse inputString variable to KeyInput static final int value. So that I could call....
doSomething(KeyInput.parse(inputString));
I know the enum valueOf, but this doesn't work here...
If you have only these two (or any other fixed number of) values, you might just enumerate them in switch:
public static int parse(String input) {
int res = -1;
switch (input) {
"TEST1":
res = TEST1;
break;
"TEST2":
res = TEST2;
break;
// ... other options
default: throw new IllegalArgumentException("unknown string");
}
}
The other option is to keep this values inside some map, so you can do this:
private static final Map <String, Integer> TESTS = new HashMap<>();
static {
TESTS.put("TEST1", 0x01);
TESTS.put("TEST2", 0x02);
// ...
}
public static int parse(String input) {
if (TESTS.containsKey(input))
return TESTS.get(input);
else
throw new IllegalArgumentException("unknown string");
}
Still, if you see the enums as an option in your case, I can consider this solution:
public enum Keys {
TEST1(0x01), TEST2(0x02);
int value;
private Keys(int value) {
this.value = value;
}
public getValue() {
return value;
}
}
Here you'll just do valueOf as you suggesed:
public static int parse(String input) {
return Keys.valueOf(input).getValue();
}
If all these options is now for your case, you should use reflection (though, I'm quite sure, it's not the case):
public static int parse(String input) {
Field[] fields = KeyInput.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(fields.getModifiers()) && field.getDeclaringClass().equals(int.class) && field.getName().equals(input)) {
return field.getInt(null);
}
}
throw new IllegalArgumentException("unknown string");
}
I want to check if there are 'bad' words in some cases such as checking IDs in register form. But I do not know how to check it.. The bottom code is what I got far with it.
String words = "admin,administrator,babo,sir,melon";
public boolean checkWord(String input) {
if(something here that i need to find??) return false;
else return true;
}
The pattern of words are divided in comma, and I really need help with it please!
The simplest thing would be to search for a word in a sorted array, like this:
private static String[] WORDS = new String[] {
"admin", "administrator", "babo", "melon", "sir"
};
public boolean checkWord(String input) {
return Arrays.binarySearch(WORDS, input) < 0; // Not found
}
Another example if you want to look for group of words inside your input
public class TestCheckWord {
static String words = "admin,administrator,babo,sir,melon";
public static void main (String args[]){
System.out.println(checkWord("Hello melon"));
System.out.println(checkWord("Hello sir"));
System.out.println(checkWord("Hello you"));
}
public static boolean checkWord(String input) {
String wordArray[] = words.split(",");
for(int i=0; i<wordArray.length; i++){
if(input.indexOf(wordArray[i])>-1)
return true;
}
return false;
}
}
and yet even another way to look for words only if your input contains only one word.(the order in the array doesn't matter in this case.
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
public class TestCheckWord2 {
public static void main (String args[]){
System.out.println(checkWord("babo"));
System.out.println(checkWord("bobo"));
}
private static String[] WORDS = {"admin", "babo", "melon", "sir", "administrator"};
private static Set<String> mySet = new HashSet<String>(Arrays.asList(WORDS));
public static boolean checkWord(String input) {
return mySet.contains(input);
}
}
public class steve {
static boolean checkWord(String input, String words) {
if(words.contains(input)) {
return true;
}
else {
return false;
}
}
public static void main(String[] args) {
String words = "admin,administrator,babo,sir,melon";
System.out.print(steve.checkWord("babo",words));
}
}
So I'm trying to write a method that reverses a given string but the catch is that it has to be a void method rather than a return method which is making this difficult. My code seems logical to me but it doesn't work so I'm hoping someone can help me figure out where I'm going wrong.
public class Reverser {
public String text, revText;
/**
* #param args
*/
public static void main(String[] args) {
Reverser greeting = new Reverser("Buildings");
greeting.reverse();
System.out.println(greeting.getText());
}
public Reverser(String _text){
text = _text;
}
public void reverse(){
int len = text.length();
if(len >= 1){
String last = text.substring(text.length() - 1, text.length());
revText += last;
text = text.substring(0, text.length() - 1);
Reverser loop = new Reverser(text);
loop.reverse();
}
}
public String getText(){
return revText;
}
}
Here's an idea:
public class Reverser {
private int idx;
private String text, revText;
public static void main(String[] args) {
Reverser greeting = new Reverser("Buildings");
greeting.reverse();
System.out.println(greeting.getText());
}
public void reverse() {
if (idx == text.length())
return;
revText = text.charAt(idx) + revText;
idx++;
reverse();
}
public Reverser(String _text) {
idx = 0;
text = _text;
revText = "";
}
public String getText() {
return revText;
}
}
The fundamental difference with respect to your answer, is that I'm using an index attribute to keep track of where exactly I am in the recursion. In that way, I don't have to modify the original text attribute.
A slighty different version to what Oscar Lopez responded is this
public class Sentence{
private String sntce, rvrse;
private int idx;
public Sentence(String sentence){
sntce = sentence;
rvrse = "";
}
/**
A method to reverse a string recursively.
#return void.
*/
void reverse(){
if (idx == sntce.length()){
sntce = rvrse;
return;
}
rvrse = sntce.charAt(idx) + rvrse;
idx++;
reverse();
}
/**
To test reverse gives the appropriate value.
#return the value of sntce.
*/
public String getText(){
return sntce;
}
}
Here's a version that uses as few instance variables as possible. Unfortunately you need at least one instance variable to hold the final result (result). Otherwise the state is passed into each recursive call.
(PS, is this homework?)
public class RecursiveVoidStringReverser {
public static void main(String[] args) {
final RecursiveVoidStringReverser reverser = new RecursiveVoidStringReverser();
reverser.reverse("Welcome to the jungle!");
System.out.println("reverser.result = " + reverser.result());
}
private String result;
public void reverse(String s) {
if ("".equals(s)) {
result = s;
} else {
reverse(s.toCharArray(), 0);
}
}
private void reverse(char[] chars, int index) {
if (index > chars.length / 2) {
result = new String(chars);
} else {
char t = chars[index];
chars[index] = chars[chars.length - index - 1];
chars[chars.length - index - 1] = t;
reverse(chars, index+1);
}
}
public String result() {
return result;
}
}
Given that a string is immutable, you cannot change it in situ. If the only requirement is that there be no return value, and it's okay simply to print out the final string (or to place it into a class variable), then this would work fine for any strings of at least one character:
public static void main(String args[])
{
reverse("", "original string");
}
public static void reverse(String reversed, String original)
{
if(original.length() <= 1)
{
System.out.println(original.charAt(0) + reversed);
// (or set it into a shared variable)
return;
}
reverse(original.charAt(0) + reversed, original.substring(1));
}
This solution is going for procedural simplicity, not memory efficiency. This produces quite an unpleasant memory footprint, essentially creating two in-memory strings for each character in the original. It is, however, very logically simple.
Of course, if you're just dumping out to console, then you can achieve the same thing using an algorithm that's pretty much the same as one with a return value:
public static void reverse(String original)
{
if(original.length() < 1) return;
System.out.print(original.charAt(original.length() - 1));
reverse(original.substring(0, original.length() - 1));
}