Simple java array string algorithms question - java

My two functions isSorted and hasDuplicate created below should work, right? My test class for the assignment wasn't working. The instructions for both are in the comments below. isSorted returns true if the string array is sorted alphabetically, and false - if not. hasDuplicate returns true if there's at least one set of duplicate strings and false - if not.
public class CheckStrings {
/**
* Returns true if the Strings in w appear in sorted order
* (alphabetical order) and false otherwise.
*
* #param w the array of Strings to check
* #return true if the Strings in w appear in sorted order
* and false otherwise.
*/
public static boolean isSorted(String[] w) {
boolean bob = true;
for (int i = 0; i < w.length-1; i++)
{
if (w[i].compareTo(w[i+1]) >= 0)
{
bob = true;
}
else
{
bob = false;
i = w.length + 50;
}
}
return bob;
}
/**
* Returns true if at least one String in w appears more than once
* and false otherwise.
*
* #param w the array of Strings to check
* #return true if at least one String in w appears more than once
* and false otherwise.
*/
public static boolean hasDuplicate(String[] w) {
boolean bob = true;
for (int i = 0; i < w.length-1; i++)
{
if (w[i].equals(w[i+1]))
{
bob = true;
i = w.length + 50;
}
else
{
bob = false;
}
}
return bob;
}
}

Submit this for your homework:
public static boolean isSorted(String[] w) {
return Arrays.stream(w).reduce("",(a, b) -> a == null || a.compareTo(b) > 0 ? null : b) != null;
}
public static boolean hasDuplicate(String[] w) {
return Arrays.stream(w).distinct().count() == w.length;
}
And who is Bob?

In case you're not allowed yet to use Java 8 Stream API, implementation of the isSorted and hasDuplicate may look as follows:
public static boolean isSorted(String[] w) {
if (null == w || w.length == 0) {
return false;
}
for (int i = 0; i < w.length-1; i++) {
if (w[i].compareTo(w[i+1]) > 0) { // or compareToIgnoreCase if case insensitive is ok
return false;
}
}
return true;
}
public static boolean hasDuplicate(String[] w) {
if (null == w || w.length < 2) return false;
Set<String> set = new HashSet<>();
for (int i = 0; i < w.length-1; i++) {
String s = w[i]; // if case-insensitive lookup needed use s = w[i].toLowerCase();
if (set.contains(s)) {
return true;
}
set.add(s);
}
return false;
}

public final class CheckStrings {
private CheckStrings() {
}
public static boolean isSorted(String... w) {
if (w == null || w.length == 0)
return false;
for (int i = 0, j = w.length - 1; j < w.length; i++, j++)
if (w[i].compareToIgnoreCase(w[j]) > 0)
return false;
return true;
}
public static boolean hasDuplicate(String... w) {
if (w == null || w.length == 0)
return false;
Set<String> unique = new HashSet<>();
for (String str : w)
if (!unique.add(str.toLowerCase()))
return false;
return true;
}
}
Output:
String[] arr = {"a", "a", "b", "b", "c", "c"};
System.out.println(CheckStrings.isSorted(arr)); // true
System.out.println(CheckStrings.hasDuplicate(arr)); // true

Related

return statement in boolean method

I do not understand what I should return. My method returns false if the last time it goes
through the for-loop it is false. If the last time is true than it returns true. But I want it to return false regardless of where the false occurred.
public class test {
public static void main(String[] args) {
int number = 4;
int[] intArray = {4, 8, 12, 16};
System.out.println(allMultipleOf(intArray, number));
}
public static boolean allMultipleOf(int[] ary, int n){
boolean a = true;
for(int i = 0; i < ary.length; i++){
if(ary[i] % n == 0){
a = true;
//System.out.println(a);
break;
} else {
a = false;
}
}
}
return a; //what should I return
}
You can return false early from the method, if we reached the end without returning false, then return true:
public static boolean allMultipleOf(int[] ary, int n) {
for (int i = 0; i < ary.length; i++) {
if (ary[i] % n != 0) {
return false;
}
}
return true;
}
It should return false, the default of the boolean is print at this place.
You can make the return statement within the method. it return true.
public static boolean allMultipleOf(int[] ary, int n) {
boolean a = true;
for(int i = 0; i < ary.length; i++) {
if (ary[i] % n == 0) {
a = true;
//System.out.println(a);
break;
} else {
a = false;
}
}
return a;
}

Check if letter 1 is always followed by number 2 and number 2 by number 3

I want to write a function that return true if if and only if
String a is always followed by String b, and String b is always followed by string c, this is what I wrote but it doesn't work :
public static boolean follows2(String s, String a, String b, String c) {
boolean res = true;
for (int i = 0; i < s.length(); i++) {
if (charAtPos(s, i).equals(a)) {
if (!(charAtPos(s, i + 1).equals(b))) {
res = false;
if (!(charAtPos(s, i + 2).equals(c))) {
res = false;
}
}
}
}
return res;
}
public static void main(String[] args) {
System.out.println(follows2(" koali oliali ", "a", "l", "i"));
// RETURN TRUE OK since for each " a" is followed by "l" then "i"
System.out.println(follows2("ipoipa", "i", "p", "a"));
//RETURN TRUE BUT IT'S NOT !
// The first " i" is followed by " p" then "o" which is not good
}
Here is the function that I wrote for:
String a is always followed by String b ( It works )
public static boolean follows(String s, String a, String b) {
boolean res = true;
for (int i = 0; i < s.length(); i++) {
if (charAtPos(s, i).equals(a)) {
if (!(charAtPos(s, i + 1).equals(b))) {
res = false;
}
}
}
return res;
}
public static String charAtPos(String s, int i) {
return String.valueOf(s.charAt(i));
}
public static void main(String[] args) {
System.out.println(follows("Arnold Barney", "r", "n"));
// RETURN TRUE because each "r" are followed by the letter "n"
System.out.println(follows("Arnold Barney", "n", "o"));
// RETURN FALSE , because not every "n" is followed by "o"
}
What can be done in my first program to make it work ?
Thank you
With recursion:
public static boolean follows(String s, String a, String b, String c) {
int ai = s.indexOf(a);
if (ai == -1) {
return true; // No more 'a' string, we're all good
}
int bi = s.indexOf(a + b);
int ci = s.indexOf(a + b + c);
if (bi != ai || ci != ai) {
return false; // Strings 'b' and 'bc' don't follow 'a', so the check failed
}
return follows(s.substring(ai + a.length()), a, b, c);
}
In reality, bi could be removed.
The problem you have is that you are not actually entering the nested if statements due to a minor flaw in your logic.
I would change it to this which checks whether i + 1 is equal to String b || i + 2 is equal to String c
public static boolean follows2(String s, String a, String b, String c) {
boolean res = true;
for (int i = 0; i < s.length(); i++) {
if (charAtPos(s, i).equals(a)) {
if (!(charAtPos(s, i + 1).equals(b)) || !(charAtPos(s, i + 2).equals(c))) {
res = false;
}
}
}
return res;
}
Because the code doesn't do what you think it does.
if you'll add some prints to the code, you'll see you never set "res" to false.
Let's debug the case you're testing:
When meet the the first letter - "i" - it entered the first if.
the next letter is "p" so you're not entered the 2nd if, so you'll continue to the next letter in the "for".
Here's my attempt (haven't tested it)
boolean hasOnlyCompleteSequences(String source, char.. chars) {
for (int s = 0; s < source.length(); s++) {
int c = 0;
if (source.charAt(s) == chars[c]) {
if (!isCompleteSequence(source, s + 1, chars, c + 1)) {
return false;
}
}
}
return true;
}
boolean isCompleteSequence(String source, int s, char[] chars, int c) {
while (s < source.length() && c < chars.length) {
// note: the indices get increased AFTER comparison
if (source.charAt(s++) != chars[c++]) {
return false;
}
}
// cover the case that the source String ends with an incomplete sequence
if (s == source.length() && c < chars.length) {
return false;
}
return true;
}
This is a much cleaner answer (tested & working great):
public static boolean follows(String s, String...strings) {
int number = 0;
for(int i = 0; i<s.length(); i++){
if(strings[number].length()+i<s.length() && s.substring(i, strings[number].length()+i).equals(strings[number]) && number+1 != strings.length) number++;
else if(number!=0 && !s.substring(i, strings[number].length()+i).equals(strings[number])) return false;
else number = 0;
}
return true;
}
It fixes many problems with your code:
Working with strings but using "charAt"
Copying the function just to add a parameter

Boolean To Return True or False in Method

Cannot figure out how to code my method, anything I try gives me compile errors. In short I need my method to iterate through my passed down boolean array. Find out if False appears consecutively more or if True appears consecutively more. In the array I provided False appears more consectively, thus it should return false back to main. I'm at a total loss right now any tips?
public class booleanTF
{
public static void main(String [] args)
{
boolean[] guess = {false,true,false,false,false,true,true};
}
public static boolean longerTF(boolean[] guess)
{
int variable = 0;
for(int x = 0; x < guess.length; x++)
{
if(guess[x]
}
}
You can use flags to check if the current element is true or false and what was the previous element of the array.
You can try the following approach. Ask me if you have any doubts
public class booleanTF {
public static void main(String[] args) {
boolean[] guess = { false, true, false, false, false, true, true };
boolean result = longerTF(guess);
System.out.println(result);
}
public static boolean longerTF(boolean[] guess) {
int variable = 0;
boolean trueFlag = false;
boolean falseFlag = false;
int trueCount = 0, falseCount = 0;
for (int x = 0; x < guess.length; x++) {
if (guess[x] == true) {
if (falseFlag == true) {
trueCount = 0;
}
trueFlag = true;
falseFlag=false;
trueCount++;
} else {
if (trueFlag == true) {
falseCount = 0;
}
falseFlag = true;
trueFlag=false;
falseCount++;
}
}
if (trueCount > falseCount) {
return true;
} else {
return false;
}
}
}
Obviously not the most effective way to do this, but:
public static boolean longerTF(boolean[] guess) {
return findMaxSeqLength(guess, true) > findMaxSeqLength(guess, false);
}
private static int findMaxSeqLength(boolean[] array, boolean value) {
int maxSeqLength = 0;
int counter = 0;
for (boolean b : array) {
counter = (b == value) ? ++counter : 0;
maxSeqLength = Math.max(maxSeqLength, counter);
}
return maxSeqLength;
}
Find the longest true sequence, find the longest false sequence and compare their lengths.
public static void booleanTF(){
boolean[] arr = {true,true,false,false,false};
int fIndex = 0;
int fMaxCount = 0;
int tIndex = 0;
int tMaxCount = 0;
for(boolean ar : arr){
if(ar){
tIndex++;
if(tIndex > tMaxCount){
tMaxCount = tIndex;
}
fIndex= 0;
}else{
fIndex++;
if(fIndex > fMaxCount){
fMaxCount = fIndex;
}
tIndex=0;
}
}
if(fMaxCount > tMaxCount){
System.out.println("False appers more " + fMaxCount);
}else if (tMaxCount > fMaxCount){
System.out.println("True appers more " + tMaxCount);
}else{
System.out.println("Same Count " + tMaxCount);
}
}

isConsecutiveStraightFlush consecutive array check [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
The assignment I have is to return true if a deck of cards is a consecutive straight flush, which means an entire deck that consists of a sequence of cards of the same suit with consecutive ranks. Since these are cards, this would mean that a card with rank 14 (A) would go BEFORE a card with rank 2.
How would I go about establishing that the order of cards goes 12,13,14,2,3 for example?
This is the Card class
public class Card {
private String suit;
private int rank;
public Card(String suit, int rank) {
super();
this.suit = suit;
this.rank = rank;
}
#Override
public String toString() {
return "[" + rank + "," + suit + "]";
}
#Override
public boolean equals(Object c2) {
if (!(c2 instanceof Card)) {
throw new RuntimeException("Illegal argument to Card.equals()");
}
Card card2 = (Card) c2;
return ((this.getSuit().equals(card2.getSuit())) &&
(this.getRank() == card2.getRank()));
}
public String getSuit() {
return suit;
}
public int getRank() {
return rank;
}
public boolean sameSuitAs(Card card2) {
return (this.getSuit().equals(card2.getSuit()));
}
public boolean sameRankAs(Card card2) {
return (this.getRank() == card2.getRank());
}
public boolean isAnA() {
if (getRank() != 14) {
return false;
}
return true;
}
public boolean isPair(Card c) {
int rank = getRank();
if (rank == c.getRank()) {
return true;
}
return false;
}
public boolean isTrio(Card c1, Card c2) {
if (c1.isPair(c2) == true ) {
if (isPair(c1) == true) {
return true;
}
}
return false;
}
public boolean isFourTuple(Card c1, Card c2, Card c3) {
if (c1.isPair(c2) == true ) {
if (c2.isPair(c3) == true) {
if (isPair(c1) == true) {
return true;
}
}
}
return false;
}
public static long countCardsBySuit(Card[] deck, Card target) {
long result = 0;
String suit = target.getSuit();
for (int i = 0; i < deck.length; i++) {
if (suit == deck[i].getSuit()) {
result ++;
}
}
return result;
}
public static boolean cardExists(Card[] deck, Card target) {
String targetsuit = target.getSuit();
int targetrank = target.getRank();
for (int i = 0; i < deck.length; i++) {
if (targetsuit == deck[i].getSuit() && targetrank == deck[i].getRank()) {
return true;
}
}
return false;
}
public static boolean consecutivePairExists(Card[] deck) {
int pairs = 0;
for (int i = 0; i < deck.length; i++) {
int targetrank = deck[i].getRank();
for (int j = 0 + i + 1; i < deck.length - 3; j ++) {
if (targetrank == deck[j].getRank()) {
pairs++;
if (pairs > 1) {
return true;
}
}
}
}
return false;
}
public static boolean pairExists(Card[] deck) {
for (int i = 0; i < deck.length; i++) {
int targetrank = deck[i].getRank();
if (i == 0) {
for (int k = 1 ; k <deck.length; k++) {
if (targetrank == deck[k].getRank()) {
return true;
}
}
}
else {
for (int j = i + 1 ; j <deck.length; j++) {
if (targetrank == deck[j].getRank()) {
return true;
}
}
}
}
return false;
}
public static boolean isConsecutiveStraightFlush(Card[] deck) {
if (deck.length > 1) {
long result = 0;
String suit = deck[0].getSuit();
for (int i = 1; i < deck.length; i++) {
if (suit == deck[i].getSuit()) {
result ++;
}
}
if (result == deck.length - 1) {
int count = 0;
int rank = deck[0].getRank();
for (int j = 1; j < deck.length; j++) {
if (rank - deck[j].getRank() == -1) {
count++;
rank = deck[j].getRank();
if (count == deck.length - 1) {
return true;
}
}
}
}
}
return false;
}
}
and this is the JUnit Test Case CardTest
import static org.junit.Assert.*;
import org.junit.Test;
public class CardTest {
Card diamond1 = new Card("Diamond", 1);
Card diamond2 = new Card("Diamond", 2);
Card spade1 = new Card("Spade", 1);
Card spade2 = new Card("Spade", 2);
Card spadeA = new Card("Spade", 14);
Card card2C = new Card("Club", 2);
Card card2S = new Card("Spade", 2);
Card card2D = new Card("Diamond", 2);
Card card2H = new Card("Heart", 2);
Card card3C = new Card("Club", 3);
Card card4C = new Card("Club", 4);
Card card5C = new Card("Club", 5);
Card card6C = new Card("Club", 6);
Card card7C = new Card("Club", 7);
Card card8C = new Card("Club", 8);
Card card9C = new Card("Club", 9);
Card card10C = new Card("Club", 10);
Card cardJC = new Card("Club", 11);
Card cardQC = new Card("Club", 12);
Card cardKC = new Card("Club", 13);
Card cardAC = new Card("Club", 14);
Card[] deck1 = { card2C, card2S, card2D, card3C };
Card[] deck2 = { card2C, card3C, card2D};
Card[] deck3 = { card2C, card3C, spadeA};
Card[] straightFlush1 = { card2C, card3C, card4C, card5C, card6C};
Card[] straightFlush2 = { cardQC, cardKC, cardAC, card2C, card3C};
Card[] emptyDeck = {};
#Test
public void testToString() {
assertTrue("Card.toString: generates incorrect String", diamond1.toString().equals("[1,Diamond]"));
assertTrue("Card.toString: generates incorrect String", spade2.toString().equals("[2,Spade]"));
}
#Test
public void testEquals() {
assertTrue("Card.equals: Yields false incorrectly", diamond1.equals(diamond1));
assertFalse("Card.equals: Yields true incorrectly", diamond1.equals(diamond2));
}
#Test
public void testSameSuitRank() {
assertTrue("Card.sameRankAs: Yields false incorrectly", diamond1.sameRankAs(spade1));
assertTrue("Card.sameSuitAs: Yields false incorrectly", diamond1.sameSuitAs(diamond2));
assertFalse("Card.sameRankAs: Yields true incorrectly", spade1.sameRankAs(spade2));
assertFalse("Card.sameSuitAs: Yields true incorrectly", spade2.sameSuitAs(diamond1));
}
#Test
public void testIsConsecutiveStraightFlush() {
assertFalse("isConsecutiveStraightFlush: returns true incorrectly", Card.isConsecutiveStraightFlush(emptyDeck));
assertFalse("isConsecutiveStraightFlush: returns true incorrectly", Card.isConsecutiveStraightFlush(deck1));
assertTrue("isConsecutiveStraightFlush: returns false incorrectly", Card.isConsecutiveStraightFlush(straightFlush1));
assertTrue("isConsecutiveStraightFlush: returns false incorrectly", Card.isConsecutiveStraightFlush(straightFlush2));
}
}
Any help would be appreciated
You need to add this special condition to your if (rank - deck[j].getRank() == -1).
if (rank - deck[j].getRank() == -1 || (rank == 14 && deck[j].getRank() == 2))
I'm not going to write any code examples towards the assignment for you, as the point is for you to write the code yourself, but I do want to give you some advice and pointers to help you along your way.
Work smarter, not harder
For a problem like this, it's generally much easier to tell if the condition is false than to tell if it is true. Here is your method:
public static boolean isConsecutiveStraightFlush(Card[] deck) {
if (deck.length > 1) {
long result = 0;
String suit = deck[0].getSuit();
for (int i = 1; i < deck.length; i++) {
if (suit == deck[i].getSuit()) {
result ++;
}
}
if (result == deck.length - 1) {
int count = 0;
int rank = deck[0].getRank();
for (int j = 1; j < deck.length; j++) {
if (rank - deck[j].getRank() == -1) {
count++;
rank = deck[j].getRank();
if (count == deck.length - 1) {
return true;
}
}
}
}
}
return false;
}
Your spending quite a lot of effort to keep track of everything so you can return true once every single check passes. If you flipped it round so that you assume it is a straight flush and return false as soon as one check fails, this method become a lot simpler.
String equality
It is a very rare case you want to use the == operator to test string equality in Java. Use string1.equals(string2) instead. For more information on this, see this answer
Experiment with operators
You're approach to use the difference in rank to test if the cards are in sequential order is fine and worked great... Until you found the requirement that the sequence is allowed to wrap back around to the start. The modulo operator (%) can be used to constrain numbers to a given range. For example, the following snippet will print keep cycling through the values, even though i will get much larger than the length of the array:
String[] values = { "one", "two", "three" };
for (int i = 0; i <= 10; i++) {
System.out.println(values[i % 3]);
}
There is a solution (not the only solution) to the wrapping rank requirement that can make use of this (hint: rank is sequential if "current rank" + 1 == "next rank").
Be careful not to turn assumptions into requirements
Does the assignment specify that the sequence Q, K, A, 2, 3 is a valid straight flush, or are you using your own understanding of poker hands?
According to Wikipedia (reliable, I know), "Q♣ K♣ A♣ 2♣ 3♣ is an ace-high flush, not a straight flush", so you might be making the assignment harder than it needs to be.
Hopefully I have given you something helpful in here. Good luck with the assignment.

Check input string to int

I have this method:
public static int parseInt(String str) {
if (isValidNumber(str)) {
int sum = 0;
int position = 1;
for (int i = str.length() - 1; i >= 0; i--) {
int number = str.charAt(i) - '0';
sum += number * position;
position = position * 10;
}
return sum;
}
return -1;
}
which converts a string into a integer. And as you can see it is (at the moment) in a if-statement with a method which checks if the input is a valid input for my purpose:
public static boolean isValidNumber(String str) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(c >= '0' && c <= '9'){
return true;
}
}
return false;
}
I want the string to be number only (negative and positive) no other is allowed. At that time a string i.e 1a1a will be converted to a integer which it shouldn't whereas -1 will not be converted. I think you guys understand what I mean. I don't know how to do that.
Please help!
Try this:
CODE:
public class validNumbers {
public static void main(String[] args) {
System.out.println(parseInt("345"));
System.out.println(parseInt("-345"));
System.out.println(parseInt("a-345"));
System.out.println(parseInt("1a5b"));
}
public static int parseInt(String str) {
String numberWithoutSign = removeSign(str);
if (isValidNumber(numberWithoutSign)) {
int sum = 0;
int position = 1;
for (int i = numberWithoutSign.length() - 1; i >= 0; i--) {
int number = numberWithoutSign.charAt(i) - '0';
sum += number * position;
position = position * 10;
}
if(isNegative(str)){
return -(sum);
}else{
return sum;
}
}
return -1;
}
/**
* Removes sign in number if exists
*/
public static String removeSign(String number){
if(number.charAt(0) == '+' || number.charAt(0) == '-'){
return number.substring(1);
}else{
return number;
}
}
/**
* Determines if a number is valid
*/
public static boolean isValidNumber(String number) {
for (int i = 0; i < number.length(); i++) {
char c = number.charAt(i);
if(c >= '0' && c <= '9'){
continue;
}else{
return false;
}
}
return true;
}
/**
* Determines if a number is negative or not
*/
public static boolean isNegative(String number){
if(number.charAt(0) == '-'){
return true;
}else{
return false;
}
}
}
OUTPUT:
345
-345
-1
-1
To check if a string is a real number you can use a method like this:
public static boolean isInteger(String str) {
try {
Integer.parseInt(str);
return true;
} catch (NumberFormatException nfe) {}
return false;
}
The problem is with your function isValidNumber. It should return a false on first occurrence of a non numeric value, as follows:
public static boolean isValidNumber(String str) {
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
if(!(c >= '0' && c <= '9')){
if (i > 0) {
return false;
}
//This will only be invoked when `i == 0` (or less, which is impossible in this for loop), so I don't need to explicitly specify it here, as I have checked for `i > 0` in the above code...
if (c != '-' && c != '+') {
return false;
}
}
}
return true;
}

Categories

Resources