This assignment involves reasoning about strings made up of uppercase letters. You will implement several static methods that appear in the same class (not shown). Here are the details.
1. The first method takes a single string parameter and returns a scrambled version of that string. The scrambling process begins at the first letter of the word and continues from left to right. If two consecutive letters consist of an "A" followed by a letter that is not an "A", then the two letters are swapped in the resulting string. Once the letters in two adjacent positions have been swapped, neither of those two positions can be involved in a future swap.
public static String scrambleWord(String word)
The method takes a given word (an empty string or a string containing only upper case letters) and returns a string that contains a scrambled version of the word according to the rules given above. The following table shows several examples of words and their scrambled versions.
Original word After scrambling
"TAN" "TNA"
"ABRACADABRA" "BARCADABARA"
"WHOA" "WHOA"
"AARDVARK" "ARADVRAK"
"EGGS" "EGGS"
"A" "A"
"" ""
the code i used but it dose not work is
public class ScrambleWord {
public static void main(String[] args) {
List<String> strList = new ArrayList<String>();
strList.add("TAN");
strList.add("ABRACADABRA");
strList.add("WHOA");
strList.add("EGGS");
strList.add("A");
strList.add("");
System.out.prentln(MainMethod.scrambleWordMeth(strList));
}
class MainMethod {
public static void scrambleWordMeth(List<String> strList) {
int curr = 0;
String res = "";
while (curr < strList.size()) {
String currentString = strList.get(curr);
for(int i = 0; i < currentString.length(); i++){
if (currentString.charAt(i) == 'A' && !(currentString.charAt(i + 1) == 'A')) {
res = res + currentString.substring(curr + 1, curr + 2);
res = res + 'A';
curr = curr + 2;
}
else {
res = res + currentString.substring(curr, curr + 1);
curr++;
}
}
if (curr < strList.size()) {
res = res + currentString.charAt(curr);
//res=res + strList.substring(curr);
}
}
return res;
}
}
}
Here is template for how to setup the methods such that the algorithm can be worked on in a more clear and isolated manner (note how the task states for "several methods"). This will prevent some issues in the posted code such as the incorrect usage of curr (which did not related to characters at all) in the inner loop. The usage of the array for the letters makes the task itself more logical to focus on without needing to perform slicing and concatenation.
static void scrambleAllWords(List<String> words) {
// Iterate through the list of word applying the scramble
// function and replacing the original item with the result.
for (int i = 0; i < words.size(); i++) {
String scrambled = scrambleWord(words.get(i));
words.set(i, scrambled);
}
}
static String scrambleWord(String word) {
// Get the letters that make up the word
char[] letters = word.toCharArray();
// Perform the algorithm on the letters
// for (int i = 0; i < ..
// Create a new string from the now-scrambled letters
return new String(letters);
}
The algorithm itself is rather simple and can be read as the following pseudo-code, which should be trivial to apply to letters as it is now an array clearly separated from the other cruft.
for i in the range [0, the number of letters in the word - 1)
if the letter at i is an 'A' and the following letter at i+1 is not an 'A' then
swap the letter at i with the letter at i+1 and
skip the next letter by advancing i by 1
(so that the current-now-next 'A' letter cannot be swapped again)
otherwise
do nothing
Related
I'm a programming newbie and I am doing a coderbyte exercise that says "
Replace every letter in the string with the letter following it in the alphabet (ie. c becomes d, z becomes a)"
i'm thinking of the following methods:
declare a string called "abcdefghijklmnopqrstuvxyz" and compare each string's char index position with the alphabet's index position, and then just bring the alphabet char that is located at the i+1 index location. But I don't know how it would work from z to a.
I've seen some techniques using ASCII values for every char but I've never done that before and not sure how it works
convert the given string into a char[] array, but then I'm not sure how I would tell the system to get me the next alphabet char
What would be the easiest way to do this?
EDIT
this is my code so far, but it doesn't work.
import java.util.*;
import java.io.*;
class Main {
public static String LetterChanges(String str) {
// code goes here
String alphabet = "abcdefghijklmnopqrstuvwxyz";
String newWord = "";
for (int i = 0; i < str.length(); i++){
for (int j = 0; j < alphabet.length(); i++){
if (str[i] == alphabet[i]){
if (alphabet[i+1].isVowel()){
newWord = newWord + toUpperCase(alphabet[i+1]);
}
else{
newWord = newWord + alphabet[i+1];
}
}
}
}
return str;
}
public static void main (String[] args) {
// keep this function call here
Scanner s = new Scanner(System.in);
System.out.print(LetterChanges(s.nextLine()));
}
}
Can't I ask for the index position of a Char that is a part of a String? in C I could do that.
Other than that not sure why it doesn't work.
I would definitely go with method 1.
I believe what you're looking for is the indexOf method on a String.
First of, I would create a method that given a character finds the next letter in the alphabet and return that. This could be done by finding the letter in your alphabet string and then fetch the letter at index+1. As you also pointed out you would need to take care of the edge case to turn 'z' into 'a', could by done with an if-statement or by having an extra letter 'a' at the end of your alphabet string.
Now all that remains to do is create a loop that runs over all characters in the message and calls the previously made method on that character and constuct a new string with the output.
Hope this helps you figure out a solution.
Assuming that there would be only lower case English letters in the given String the most performant way would be to add +1 to every character, and use either if-statement checking whethe the initial character was z or use the modulo operator % as #sp00m has pointed out in the comment.
Performing a search in the alphabetic string (option 1 in your list) is redundant, as well extracting array char[] from the given string (option 3).
Checking the edge case:
public static String shiftLetters(String str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char next = str.charAt(i);
if (next == 'z') result.append('a'); // checking the edge case
else result.append((char) (next + 1));
}
return result.toString();
}
Applying modulo operator:
public static String shiftLetters(String str) {
StringBuilder result = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char next = (char) ((str.charAt(i) - 'a' + 1) % 26 + 'a');
result.append(next);
}
return result.toString();
}
main()
public static void main(String[] args) {
System.out.println(shiftLetters("abc"));
System.out.println(shiftLetters("wxyz"));
}
Output:
bcd // "abc"
xyza // "wxyz"
So I have been learning Java for a little over a month now, and I have a hang man game that I am making but I am having trouble with replacing characters in my string. I have it written so you have two strings, one is called "word" which contains the word to be guessed and the other is called "clone" which is a clone of the word that replaces all the characters with underscores. Then as you guess a letter it checks the string "word" to make sure it contains it, and if it does it replaces the underscore in "clone" with that letter.
while (this.guessesLeft >= 0) {
char letter;
int letterIndex;
getGuess();
if(this.word.contains(this.letterGuessed)) {
StringBuilder newString = new StringBuilder(this.clone);
letterIndex = this.word.indexOf(this.letterGuessed);
letter = this.word.charAt(letterIndex);
newString.setCharAt(letterIndex, letter);
this.clone = newString.toString();
} else {
this.guessesLeft--;
}
printGameBoard();
}
The problem that I'm having is that if you guess a letter and the string contains two of a character it only shows one. For example, here is my output if the word "burrito" is used.
Guess a letter: r
bur____
You have 5 guess left before you die!
Guess a letter: i
bur_i__
You have 5 guess left before you die!
Guess a letter: r
bur_i__
You have 5 guess left before you die!
How would I edit my game logic so that it if the letter "r" is guessed it puts both R's in the string and not just one? Thanks in advance for the help!
You need to look for all the indexes for your letter, then replace them all.
At the moment you only look for the first one.
To find all indexes, look for a first occurrence of the letter, then if you find one (indexOf returns a positive value), keep looking from that last position using the indexOf(int ch, int fromIndex) method until you have found them all (indexOf returns -1).
Here is an example:
if(this.word.contains(this.letterGuessed)) {
// look for an occurrence,
// if you have one, keep looking for others until you have them all (ie: index = -1)
List<Integer> indexes = new ArrayList<>();
int index = this.word.indexOf(this.letterGuessed);
while (index >= 0) { // <- that will loop until the indexOf returns a -1
indexes.add(index);
index = this.word.indexOf(this.letterGuessed, index+1);
}
// replace at all the found indexes
StringBuilder newString = new StringBuilder(this.clone);
for(int letterIndex : indexes) {
char c = this.word.charAt(letterIndex);
newString.setCharAt(letterIndex, c);
}
this.clone = newString.toString();
} else {
this.guessesLeft--;
}
You could also do that in one go, without holding the indexes in a list:
if(this.word.contains(this.letterGuessed)) {
StringBuilder newString = new StringBuilder(this.clone);
int index = this.word.indexOf(this.letterGuessed);
while (index >= 0) {
char c = this.word.charAt(index);
newString.setCharAt(index, c);
index = this.word.indexOf(this.letterGuessed, index+1);
}
this.clone = newString.toString();
System.out.println("clone = " + clone);
} else {
this.guessesLeft--;
}
I have a strings that contain only digits. String itself would look like this "0011112222111000" or "1111111000". I'd like to know how can I get an array of substrings which will consist of strings with only one digit.
For example, if I have "00011111122233322211111111110000000" string, I 'd like it to be in string array(string[]) which contains ["000","111111","222","333","222","1111111111","0000000"].
This is what I've tried
for (int i = (innerHierarchy.length()-1); i >= 1; i--) {
Log.e("Point_1", "innerHierarchy " + innerHierarchy.charAt(i));
c = Character.toChars(48 + max);
Log.e("Point_1", "c " + c[0]);
if (innerHierarchy.charAt(i) < c[0] && innerHierarchy.charAt(i - 1) == c[0]) {
Log.e("Point_1", "Start " + string.charAt(i));
o = i;
} else if (innerHierarchy.charAt(i) == c[0] && innerHierarchy.charAt(i - 1) < c[0]) {
Log.e("Point_1", "End " + string.charAt(i));
o1 = i;
string[j] = string.substring(o1,o);
j=j+1;
}
}
But this code won't work if string looks like this "111111000"
Thank you.
I have "00011111122233322211111111110000000" string, I 'd like it to
be in string array(string[]) which contains
["000","111111","222","333","222","1111111111","0000000"]
One approach I can think of right now (O(n)) (might not be the most efficient but would solve your problem) would be traversing the string of numbers i.e. ("00011111122233322211111111110000000" in your case )
and if char at that position under consideration is not same as char at previous position then making string till that part as one string and continuing.
(approach)
considering str= "00011111122233322211111111110000000"
//starting from position 1 (ie from 2nd char which is '0')
//which is same as prev character ( i.e 1st char which is '0')
// continue in traversal
// now char at pos 2 which is again '0'
// keep traversing
// but then char at position 3 is 1
// so stop here and
//make substring till here-1 as one string
//so "000" came as one string
//continue in same manner.
code
import java.util.*;
public class A {
public static void main(String []args){
String str = "00011111122233322211111111110000000";
str+='-'; //appended '-' to get last 0000000 as well into answer
//otherwise it misses last string which i guess was your problem
String one_element ="";
int start=0;
for(int i=1;i<str.length();i++){
if(str.charAt(i)== str.charAt(i-1) )
{
}
else{
one_element = str.substring(start,i);
start = i;
System.out.println(one_element);//add one_element into ArrayList if required.
}
}
}
}
I have printed each element here as string , if you need an array of all those you can simply use an array_list and keep adding one_element in array_list instead of printing.
I am kind of stuck on this java problem involving returning the number of isomorphic pairs in an array of Strings. The code I have written keeps returning incorrect number of isomorphic word pairs.
The definition of isomorphic words is given as follows: Two words are called isomorphic if the letters in one word can be remapped to get the second word. Remapping a letter means replacing all occurrences of it with another letter. The ordering of the letters remains unchanged. No two letters may map to the same letter, but a letter may map to itself.
For example, the words "abca" and "zbxz" are isomorphic because we can map 'a' to 'z', 'b' to 'b' and 'c' to 'x'.
I am not inlcuding the getMap method which I call in the function. The getMap method take any string as input, and returns a map where the keys are the letters in the string, and the corresponding values are the number of times the letter appears in the string.
public class IsomorphicWords {
public int countPairs(String[] words) {
Set <String> pairs = new HashSet<String>();
for (String word:words){
Map noOfOccurencesOfEachLetter= getMap(word);
ArrayList<Integer> valuesFromFirstWord = new ArrayList<Integer>(noOfOccurencesOfEachLetter.values());
Collections.sort(valuesFromFirstWord);
java.util.List<String> list = new ArrayList<String>(Arrays.asList(words));
list.remove(word);
String[] oneLessWord = list.toArray(new String[words.length-1]);
for(String secondWord:oneLessWord){
Map secondNoOfOccurencesOfEachLetter = getMap(secondWord);
ArrayList<Integer> valuesFromSecondWord = new ArrayList<Integer>(secondNoOfOccurencesOfEachLetter.values());
Collections.sort(valuesFromSecondWord);
if (valuesFromFirstWord.equals(valuesFromSecondWord)){
pairs.add(""+word+","+secondWord+"");
}
else{
continue;
}
}
}
return pairs.size()/2;
public Map getMap(String word){
HashMap<String,Integer> noOfOccurencesOfEachLetter= new HashMap<String,Integer>();
for (int i=0;i<word.length();i++){
char letter = word.charAt(i);
String letterInDictionary= Character.toString(letter);
if (noOfOccurencesOfEachLetter.containsKey(letterInDictionary)==true){
int count= noOfOccurencesOfEachLetter.get(letterInDictionary);
noOfOccurencesOfEachLetter.put(letterInDictionary, count+1);
}
else{
noOfOccurencesOfEachLetter.put(letterInDictionary, 1);
}
}
return noOfOccurencesOfEachLetter;
}
}
I'd really appreciate any feedback you can give me on this code.
Thanks,
Junaid
The reason why it gives the incorrect answer probably comes from you take the letter count, and don't look at the position that they have in both words. The first solution that comes up in me, is to create a new array in which you translate the letters to the index of the first occurrence of this letter for each word. For example: "abcd" would be "0123", "abca" would be "0120" and "fhjf" would be "0120" as well. Then you can simply compare the results. I hope this helps...
public int countPairs(String[] words) {
int isomorphicPairs = 0;
for (int i = 0; i < words.length; i++) {
for (int j = i+1; j < words.length; j++) {
if (words[i].length() == words[j].length()) {
String tmp = new String(words[j]);
for (int k = 0; k < tmp.length(); k++)
tmp = tmp.replaceAll("" + tmp.charAt(k), "" + words[i].charAt(k));
if (words[i].equals(tmp)) isomorphicPairs++;
}
}
}
return isomorphicPairs;
}
So I was at a programming interview a few months ago and this problem tripped me up for some reason. There are a couple of solutions I can think of but most of them seem extremely inefficient. Though I've been programming in some capacity for years, I'm currently in college for a CS degree so my point of reference may be incomplete. I was hoping someone here might offer up some possible solutions:
"Given a set of strings and associated numerical 'values,' assemble a palindrome from these string whose value (defined by the sum of the strings used to create it) is the highest possible."
There were no limits to how many strings could be provided, some strings may not be used.
Example:
"asd" - 3
"dsa" - 5
"appa" - 1
Result would be "asdappadsa" with a value of 9.
My thought would be to try all strings in all orders, then drop off one, starting with the lowest valued one, but that solution is O(N!) and I'd assume that's not ok.
(Preferred languages are C and Java, but whatever works)
EDIT: Clarification. Each string provided can only be used once, and has to be used exactly as provided, though you may choose to not use any of the strings in your palindrome. You can not use substrings of provided strings, nor can you reverse the string.
Replace "all strings" with "all palindromes" and the problem space becomes much smaller.
Divide the strings into 26 subsets.
Strings beginning with x (for 'a' <= x <= 'z')
[or whatever the set of "letters" is]
Now divide them into another 26 subsets
Strings ending with y ( for 'a' <= y <= 'z')
Note each string appears in a "begins with" set and an "ends with" set.
Use these sets to guide creation of all possible palindromes.
Start with two empty strings: prefix and suffix
for each string in the original set
assign it to the prefix
call recursiveFunction(prefix, suffix)
def recursiveFunction(prefix, suffix):
if prefix + <anything> + suffix cannot form a palindrome return
if prefix + suffix is a palindrome, remember it
while you have unused strings
if the suffix is shorter than the prefix
Look at the first unmatched character in the prefix
for each unused string that ends in that character
call recursiveFunction(prefix, string + suffix)
else if prefix is shorter than suffix
look at the last unmatched character in the suffix
for each unused string that ends with that character
call recursiveFunction(prefix + string, suffix)
else // suffix and prefix have equal lenghths
for each unused string
call recursiveFunction(prefix + string, suffix)
Be sure to mark the string used in both begins with and ends when you use it.
And be sure to consider the impact of recursion on the "used" marker.
Then pick the palindrome with the best score.
With palindrones, you can split the string into 3 substrings, ABC. There is potential within the set to find string reversals, so when you get a hit you can keep track of these strings for useage in substring A and C. If you don't get a reversal hit within the entire set, you just need to find the largest string (or string with the highest value) that is a reflection of itself. Not the best solution, I'm sure, but I did it for fun anyways so I may as well share. Also, I made no efforts to make this code "clean", so its a bit ugly, but it works.
public class Main {
private static String[] set = new String[] { "asdf" , "kjdij", "skjdihi", "ddidid" , "ididid", "iddid", "oihu", "uhio", "fdsa", "ajsja" };
public static void main(String[] args){
//Used for a couple of for loops...
int count;
Map<String, String> map = new HashMap<String,String>(); //Hold the strings and their reversals in a hashmap for quick lookups.
/* Think of the palindrome as 3 substrings, A, B, and C. */
ArrayList<String> A = new ArrayList<String>();
ArrayList<String> B = new ArrayList<String>();
ArrayList<String> C = new ArrayList<String>();
count = set.length;
String[] reverse_set = new String[count];
for(int x = 0; x < count; x++){
String reverse = new StringBuilder(set[x]).reverse().toString();
/* Check strings that would work for section B, since it's a set, we know that if it could work for B,
* it couldn't work for A or C - since a set contains no duplicates. */
if(reverse.equals(set[x])){
B.add(set[x]);
} else {
/* Otherwise, we'll have to check to see if it would work for A and C */
reverse_set[x] = reverse;
map.put(set[x], reverse);
}
}
/* Check the map for reverse string hits, we know that if another string exists in set S such that S(X) == R(X) it can work for substring
* A and C. */
int map_size = map.size();
int hit_count = 0;
for(int i = 0; i < map_size; i++){
String s = map.get(reverse_set[i]);
if(s != null){
hit_count++;
A.add(set[i]);
C.add(reverse_set[i]);
map.remove(set[i]); //remove the reflection, so we don't get duplicates
}
}
/* Find the longest string in B, since we'll have to do this even if was had any hits in the previous loop. */
String b = null;
if(B.size() > 0){
int length = 0;
for(String x : B){
int mLength = x.length();
if(mLength > length){
b = x;
length = mLength;
}
}
}
/* Build the palinedrome */
String palineString = "";
if(hit_count == 0 && b != null){
palineString = b;
} else {
for(String x : A){
palineString += x;
}
if(b != null){
palineString += b;
}
count = C.size();
for(int y = (count - 1); y >= 0; y--){
palineString += C.get(y);
}
}
if(checkPalindrome(palineString)){
System.out.print("The Palindrone is: " + palineString + " Score: " + Integer.toString(palineString.length()));
} else {
System.out.print("Oops...");
}
}
private static boolean checkPalindrome(String x){
if(x.equals(new StringBuilder(x).reverse().toString())){
return true;
} else {
return false;
}
}
}
Output:
The Palindrone is: asdfoihuajsjauhiofdsa Score: 21
EDIT:
Note: for the time being, I used the string's length as the "assigned value", I'll make an edit later to account for assigning random values to strings, but it won't make too much of a difference, since it only adds a few extra use cases to check for.