Permutations, Recursion - java

I have an assignment: User enters a String, example ABCD and the program has to give out alll the permutations.
I don't want the whole code just a tip. this is what i got so far in thery i got nothing implemented.
Taking ABCD as an example:
get factorial of length of String in this case 4! = 24.
24/4 = 6 So first letter has to change after 6. so far so good.
than get factorial of remaining letters which are three 3! = 6.
6/3 =2 2 places for each letter. from here i don't know how it can continue to fill 24 places.
With this algorithm all i will have is
ABCD
ABD
AC
AC
AD
AD
B
B
B
B
B
B
.
. (continues with 6 C's and 6 D's)
I think my problem is i do not have alot of experience with recursive problems so who can suggest some programs to program to help me get to know recursion better please do.
Thanks! If somethings aren't clear please point out.

You are right that recursion is the way to go. The example you worked thru w/ the little bit of math was all correct, but kind of indirect.
Here's some pseudocode:
def permute(charSet, soFar):
if charSet is empty: print soFar //base case
for each element 'e' of charSet:
permute(charSet without e, soFar + e) //recurse
example of partial recursion tree
permute({A,B,C}, '')
/ | \
permute({B,C}, 'A') permute({A,C}, 'B') permute({A,B}, 'C')
/ \
permute({A}, 'BC') permute({C}, 'BA')
|
permute({}, 'BCA')<---BASE CASE, print 'BCA'
EDIT
To handle repeated characters without duplicating any permutations. Let unique be a function to remove any repeated elements from a collection (or string that is being treated like an ordered character collection thru indexing).
1) Store results (including dupes), filter them out afterwards
def permuteRec(charSet, soFar):
if charSet is empty: tempResults.add(soFar) //base case
for each element 'e' of charSet:
permute(charSet without e, soFar + e) //recurse
global tempResults[]
def permute(inString):
permuteRec(inString, '')
return unique(tempResults)
print permute(inString)
2) Avoid generating duplicates in the first place
def permute(charSet, soFar):
if charSet is empty: print soFar //base case
for each element 'e' of unique(charSet):
permute(charSet without e, soFar + e) //recurse

Make a method that takes a string.
Pick a letter out of the string and output it.
Create a new string with the input string minus the letter you picked.
call the above method with the new string if it has at least 1 character
do this picking of one letter for each possible letter.

Related

I was trying to solve the leetcode 1996 number of weak characters using a simple traversing approach but this is only working on test cases, any solut

Solution:
I was trying to solve the Leetcode 1996 number of weak characters using a simple traversing approach, but this only works on test cases.
Description as follows:
You are playing a game that contains multiple characters, and each of the characters has two main properties: attack and defense. You are given a 2D integer array properties where properties[i] = [attacki, defensei] represents the properties of the ith character in the game.
A character is said to be weak if any other character has both attack and defense levels strictly greater than this character's attack and defense levels. More formally, a character i is said to be weak if there exists another character (j) where attack[j] > attack[I] and defense[j] > defense[I].
Return the number of weak characters.
Working perfectly on sample testcase but why not on other like as: input: [[1,1],[2,1],[2,2],[1,2]] Expected output: 1 output recieved=0.
class Solution {
public int numberOfWeakCharacters(int[][] properties) {
int answer=0;
for(int i=0;i<properties.length-1;i++){
if((properties[i][0]<properties[i+1][0] && properties[i][1]<properties[i+1][1]) ||
(properties[i][0]>properties[i+1][0] && properties[i][1]>properties[i+1][1]))
++ans;
}
return answer;
}
}

Convert in reverse ascii to whole decimal in Java

Hi all and thank you for the help in advance.
I have scoured the webs and have not really turned up with anything concrete as to my initial question.
I have a program I am developing in JAVA thats primary purpose is to read a .DAT file and extract certain values from it and then calculate an output based on the extracted values which it then writes back to the file.
The file is made up of records that are all the same length and format and thus it should be fairly straightforward to access, currently I am using a loop and and an if statement to find the first occurrence of a record and then through user input determine the length of each record to then loop through each record.
HOWEVER! The first record of this file is a blank (Or so I thought). As it turns out this first record is the key to the rest of the file in that the first few chars are ascii and reference the record length and the number of records contained within the file respectively.
below are a list of the ascii values themselves as found in the files (Disregard the " " the ascii is contained within them)
"#¼ ä "
"#g â "
"ÇG # "
"lj ‰ "
"Çò È "
"=¼ "
A friend of mine who many years ago use to code in Basic recons the first 3 chars refer to the record length and the following 9 refer to the number of records.
Basically what I am needing to do is convert this initial string of ascii chars to two decimals in order to work out the length of each record and the number of records.
Any assistance will be greatly appreciated.
Edit...
Please find below the Basic code used to access the file in the past, perhaps this will help?
CLS
INPUT "Survey System Data File? : ", survey$
survey$ = "f:\apps\survey\" + survey$
reclen = 3004
OPEN survey$ + ".dat" FOR RANDOM AS 1 LEN = reclen
FIELD #1, 3 AS RL$, 9 AS n$
GET #1, 1
RL = CVI(RL$): n = CVI(n$)
PRINT "Record Length = "; RL
reclen = RL
PRINT "Number of Records = "; n
CLOSE #1
Basically what I am looking for is something similar but in java.
ASCII is a special way to translate a bit pattern in a byte to a character, and that gives each character a numerical value; for the letter 'A' is this 65.
In Java, you can get that numerical value by converting the char to an int (ok, this gives you the Unicode value, but as for the ASCII characters the Unicode value is the same as for ASCII, this does not matter).
But now you need to know how the length is calculated: do you have to add the values? Or multiply them? Or append them? Or multiply them with 128^p where p is the position, and add the result? And, in the latter case, is the first byte on position 0 or position 3?
Same for the number of records, of course.
Another possible interpretation of the data is that the bytes are BCD encoded numbers. In that case, each nibble (4bit set) represents a number from 0 to 9. In that case, you have to do some bit manipulation to extract the numbers and concatenate them, from left (highest) to right (lowest). At least you do not have to struggle with the sequence and further interpretation here …
But as BCD would require 8-bit, this would be not the right interpretation if the file really contains ASCII, as ASCII is 7-bit.

Function displaying wrong character code value

Background to my problem
Hi, I am just attempting to complete an exercise on project Euler which states that I must read all names from a ".txt" file and add all the character codes for each character within that string etc. As I was doing the exercises I realized that the wrong character codes is being displayed.
This is the full details for my problem from project Euler
Using names.txt (right click and 'Save Link/Target As...'), a 46K text
file containing over five-thousand first names, begin by sorting it
into alphabetical order. Then working out the alphabetical value for
each name, multiply this value by its alphabetical position in the
list to obtain a name score.
For example, when the list is sorted into alphabetical order, COLIN,
which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the
list. So, COLIN would obtain a score of 938 × 53 = 49714.
What is the total of all the name scores in the file?
My Question
why is my code displaying the value "67" for the character "C" when the actual character code value for "C" is 3? . Thanks in advance.
private static int NameValue(string name)
{
string StrimName = name.Substring(1, name.Length-2); // name ---> COLIN
Console.WriteLine(StrimName[0] + 0); // should print 3 because character code for "C" Is 3 but result is 67...
return 0;
}
It prints a number from an ASCII table: http://www.asciitable.com/
You should replace it with:
Console.WriteLine((StrimName[0]-64) + 0);
to receive what you want. It turns out you want to count 'A' as one, and its number in ASCII table is 65, therefrom I subtract 64.
Every character has a number in the ascii code,
The ascii-code dor 'C' is 67, This is why you see 67.
You can see here a table for ascii code

An Array within an Array?

Ok so as I plod along in my classes in Java coding I was asked to use this code to count the instances of lowercase letters that were generated by a method for a character array. I can follow the code up to the point it throws out stuff like. "counts[chars[currentIndex] - 'a']++;"
So yes, the codes says it's making a public method called countLetters, it needs to be called somewhere in the main body and needs a character array parameter to fire up, got that. It creates a integer array called counts and it's size is 26, (same size as total # of lowercase letters in alphabet, got that.) It then fires up a for function, commonly needed for arrays. Creates a variable called currentIndex, default value 0, while current index is less than the size of chars character array do the stuff below. Then it gets to what the for loop actually is DOING. and uh, what the hell is it doing? it's increasing the size of count's index? The whole thing is weird, like some array within an array and subtracting the numeric value of lowercase 'a'? It's modifying the currentIndex of count somehow. Why is subtracting the numeric value of 'a' necessary? Wouldn't - 26 suffice here?
Can somebody please explain slowly and in complete layman's terms how this is working? I'm really a novice programmer at best and this stuff is confusing the hell out of me, so please bear with me, I'm not the sharpest tool in the shed, as the Smashmouth song goes. All joking aside, I'd appreciate if you could break down what is going on.
//count the occurrences of each letter
public static int[] countLetters(char[] chars){
//declare and create an array of 26 int
int[] counts = new int[26];
//for each lowercase letter in the array, count it
for (int currentIndex = 0; currentIndex < chars.length; currentIndex++)
counts[chars[currentIndex] - 'a']++;
return counts;
}
Alrightey so this line:
counts[chars[currentIndex] - 'a']++;
Is short for all of this:
// Get the current character from the array:
char character = chars[currentIndex];
// Characters are just numbers. Check out e.g. an "ASCII table".
// So, let's start treating them like numbers and take 'a' from that.
int indexInCounts = character - 'a';
// Increase the count for that letter:
counts[indexInCounts] = counts[indexInCounts] + 1;
Why 'a'?
Arrays start at 0 - you mentioned that in your question so it looks like you've got the hang of those so far. So, if we want counts[0] to represent the number of a's in the input, then we'll need to put 'a' at 0.
'a'-'a' is 0.
'b'-'a' is 1.
etc.
So, conveniently, taking away 'a' from our input character gives us a number that'll work great for our array index.
Letters taking away letters is so weird!
Computers only really deal with numbers. Pull up an ASCII table, and you get an easy way to see how letters map to the underlying numbers (in the ASCII encoding scheme):
97: Lowercase 'a'
98: Lowercase 'b'
99: Lowercase 'c'
.. And so on!
Hopefully you can see where that's going!
98 (b) - 97 (a) gives us that index of 1, for example.
Try it out, but don't forget those brackets!
If you want to experiment, you could swap out that line for the ones above, but don't forget the brackets of your for loop!
for(int a=...)
doSomething(); // Only this first line is looped
doSomethingElse(); // This happens *once*!
This is called implicit brackets and is also just a convenience thing. So, here's the full, expanded version:
for (int currentIndex = 0; currentIndex < chars.length; currentIndex++)
{
// Everything in those brackets will be repeated.
// Get the current character from the array:
char character = chars[currentIndex];
// Characters are just numbers. Check out e.g. an "ASCII table".
// So, let's start treating them like numbers and take 'a' from that.
int indexInCounts = character - 'a';
// Increase the count for that letter:
counts[indexInCounts] = counts[indexInCounts] + 1;
}
Am I supposed to write stuff like that straight away?
Not really, no! In reality, you'd typically start out with the expanded version seen above (although most would immediately use counts[indexInCounts]++;). When a variable is only used once it's often easier to then substitute the actual value in - like this, without all those comments:
char character = chars[currentIndex];
int indexInCounts = character - 'a'; // Character is only used once.
counts[indexInCounts]++; // indexInCounts is only used once.
Step 2:
char character = chars[currentIndex];
counts[character - 'a']++; // Character is only used once.
Finally, the magical line is back:
counts[chars[currentIndex] - 'a']++;
Predicting errors
If you think you've got the hang of it then try and predict what error you'll get if you chuck an evil space character into the input.
Here's a spoiler:
You'll get an index out of range exception. Space is 32 on that ASCII table. 32 - 97 is very much a negative number, and very much out of range of the acceptable 0-25 of your counts array!
P.s. I'm not the sharpest tool in the shed - I will forever and always disagree (except about the song; that's great) :) Everybody has to start somewhere and you're giving it a try so I wish you all the best!

Java search a string for a substring UNLESS preceded by specific character

I'm attempting to write a Java program that searches for a specific substring (xyz) within a user-entered string, and keeping a running count, unless that substring is preceded by a period. At this point in the class, we've only used charAt and length, so if possible I need to stick to that. Additionally, we haven't used regular expressions at all, so that's out the window too.
I've managed to get the program working as desired, with one notable exception: if the String entered begins with a period, it fails to count any successive matches. This is what I've got so far:
System.out.println("Give me a String:");
String s1 = kb.nextLine();
int index = 0;
int count = 0;
while(index <= s1.length() - 1 && s1.charAt(index) != '.')
{
if(s1.charAt(index) == 'x' && s1.charAt(index + 2) == 'z')
{
count++;
}
index++;
}
System.out.println(count);
You can simply check the input string whether it starts with period. If so then you can use the following piece of code to handle the validation.
if(s1.charAt(0)!='.')
{
while(index <= s1.length() - 1 && s1.charAt(index) != '.')
{
if(s1.charAt(index) == 'x' && s1.charAt(index + 2) == 'z')
{
count++;
}
index++;
}
}
else
{
index=1;
while(index <= s1.length() - 1 && s1.charAt(index) != '.')
{
if(s1.charAt(index) == 'x' && s1.charAt(index + 2) == 'z')
{
count++;
}
index++;
}
}
System.out.println(count);
}
As this seems like a homework type of question I will attempt to guide you in the right direction first and provide a solution at a later time. I strongly encourage you to work through the problem on your own first to the best of your ability before you look at my solution (once I post it) and to read this page before going ANY further
First, consider the kinds of inputs you could receive. Since you didn't specify any limitations you could get things like:
"" (empty string)
"\n" (whitespace)
"x" (a single character)
"xx" (two characters string)
"abc" (string of correct length, but not containing your substring)
".xyz" (the substring to be ignored)
I could go on, but I'm sure you can come up with all the various combinations of weird things you might receive. These are just a few examples to get you started (along with those I posted in the comments already)
Next, think about what you need your algorithm to do. As I said in the comments it sounds like you want to count the occurrences of the substring "xyz" while ignoring the occurrences of the substring ".xyz". Now consider how you're going to look for these substrings - you're going to advance one character at a time from left to right across the String looking for a substring that matches one of these two possibilities. When you find one of them you'll either ignore it or count it.
Hopefully this helps and as I said, I will post a solution later after you've had some time to wrestle with the code. If you do solve it go ahead and post your solution (maybe edit your question to add the new code or add an answer) Finally I once again strongly urge you to read this page if you have not already.
EDIT #1:
I wanted to add a little more information and that is: you already have a pretty good idea of what you need to do in order to count your "xyz" substring at this point - despite the small flaw in the logic for inputs like "xaz", which is easily fixable. What you need to focus on is how to ignore the substring ".xyz" so think about how you could implement the ignore logic, what does it mean to ignore it? Once you answer that it should start coming together for you.
EDIT #2:
Below you will find my solution to the problem. Once again it's important to understand how the solution works not just copy and paste it. If you simply copy my code without understanding it you're cheating yourself out of the education that you're trying to gain. I don't have time at the moment to describe in detail why and how this code works, but I do plan to edit again later to add those details.
import java.util.Scanner;
public class Main {
private static Scanner scan = new Scanner(System.in);
public static void main(String[] args) {
System.out.println("Give me a String:");
String s1 = scan.nextLine();
System.out.println(countSubstrings(s1));
}
public static int countSubstrings(String s1){
int index = 0;
int count = 0;
while (index < s1.length()-2) {
if(s1.charAt(index) == '.' && s1.charAt(index+1) != '.'){
index++;
}
else if (index+2 < s1.length() && s1.charAt(index) == 'x' && s1.charAt(index + 1) == 'y'
&& s1.charAt(index + 2) == 'z') {
count++;
index+=2;
}
index++;
}
return count;
}
}
EDIT #3:
Here is the nuts and bolts of why the above code does what it does. First, we think about the fact that we're looking for 3 items (a triple) in a specific order within an array and if we see a fourth item (a period) immediately preceding the first item of the triple then we need to ignore the triple.
Per my previous edit we need to define what it means to ignore. In this case what we mean is to simply not count it and move on with our search for valid substrings to count. The simplest way to do that is to advance the index without incrementing the count.
So, ask yourself the following:
When should my loop stop? Since we're looking for triples we know we can stop if the length of the input String is less than 3 or when there are less than 3 characters left in the String that we have not examined yet. For example if the input is "xyzab" by the time we get to index 3 we know there's no possible way to form a triple where "a" is the first character in the triple and that therefore our counting is done.
Is there ever a time when I would not want to skip the next 3 characters after a period? After all the goal is to look for triples so wouldn't I want to skip 3 characters not just 1? Yes there is a time when you do NOT want to skip 3 characters and that's when you have something like ".axyz" because a valid triple could start as soon as the 2nd character past the period. So in fact you want to skip only 1 character.
This, and the fact that index is always incremented by 1 at the end of the loop (more on this later), is why the first condition inside the while only advances the index by 1:
if(s1.charAt(index) == '.' && s1.charAt(index+1) != '.'){
index++;
}
Is there ever a time when I would see a period and not wish to ignore (skip) the next character? Yes, when the next character is another period because it could indicate that another triple needs to be skipped. Consider the input "..xyz" which would result in a wrong answer if you encounter the first period and skip the second period since your algorithm could see the next three characters as a valid triple but in fact it is invalid because of the second period.
This is why the second half of the above condition exists:
`&& s1.charAt(index+1) != '.'`
Now ask yourself how to identify a valid triple. I'm sure by now you can see how to do this - check the current character, the next character, and the character after that for the values you want. This logic is the latter portion of the second if condition within the while:
s1.charAt(index) == 'x' && s1.charAt(index + 1) == 'y'
&& s1.charAt(index + 2) == 'z'
Whenever you're using calculations like index +1 or index +2 inside of a loop that is incrementing the index until it reaches a boundary you have to consider the possibility that your calculation will exceed the boundary because you can't rely on the loop to check this for you as the loop will not perform that check until either the end or beginning of the loop (depending on which kind of loop it is)
Considering the above you must ask yourself: How do I prevent out of boundary scenarios when I use these index+1, index+2, etc types of calculations? The answer is to add another piece to your condition:
index+2 < s1.length()
You may be wondering - why not add two checks since we're using index+1 and index+2? We only need one check to see if the greatest index we use will exceed the boundary in this case. If index +2 is beyond the bounds we don't care if index+1 is or is not because it won't matter we can't possibly have a matching substring.
Next, inside of the second if inside the while you see there is code to increment the index by 2: index+=2; This is done for efficiency since once we have identified a triple we know there is no way to form another triple with characters that are already part of another triple. Therefore we want to skip over them and just like the first bullet point we take advantage of the loop incrementing the index so we only need to increment by 2 and let the loop add the extra 1 later.
Finally we reach the end of the logic within the loop. This part you're already familiar with and that's the index++; which simply increments the position within the String that we're currently examining. Note that this works in tandem with the first bullet point. Take the example from the first bullet point of ".axyz". There is a period in index 0 and the character in index 1 is not another period so the logic from the first bullet point will increment index by 1, making it 1. At the end of the loop index is incremented again making it 2 thereby skipping over the period - at the start of the next loop index is 2, it was never 1 at the start of the loop.
Well, I hope this helps to explain how it all works and illustrate how to think about these sorts of problems. The basic principle is to visualize where your current element is and how you can use that to achieve your goal. At the same time think about what kinds of properties the different elements of your program have and how you can take advantage of them - such as the fact that once you identify a triple it is safe to skip over those characters because they have the property of only being usable once. As with any program you always want to try to create as many test inputs as you can to test all the weird boundary cases that might occur to ensure the correctness of your code. I realize you probably are not familiar with JUnit but it is a very useful tool and you might try researching the basics of using it when you have a little spare time, and the bonus is that if you use the Eclipse IDE it has integrated JUnit functionality you can use.

Categories

Resources