DEV Community

loading...

Check if the chain has the same amount

josktgui profile image José Oscátegui ・1 min read

Check if a string has the same amount of 'x' and 'o'. The method must return a Boolean value and must not be case-sensitive. The string can contain any char.

Discussion

pic
Editor guide
Collapse
ganeshtata profile image
Tata Ganesh

Python solution -

def equal_x_and_o(input_string):
    x_count = 0
    o_count = 0
    for c in input_string:
         if c == "x" or c == "X":
            x_count += 1
         elif c == "o" or c == "O":         
            o_count +=1
    return x_count == o_count

Thank you @Pierre for pointing out the error.

Collapse
pbouillon profile image
Pierre Bouillon

Hey @ganeshtata !
I think you missed an uppercase in your elif :)

elif c == "o" or c == "o": 

instead of

elif c == "o" or c == "O": 

To dig a little deeper, I suggest you to see some very useful string methods in Python !

Collapse
ganeshtata profile image
Tata Ganesh

Thank you for that! I had not noticed it. Yes, there are some awesome string methods in Python, but I didn't use any of them here because I wanted to finish the count(s) in one pass of the string. Doing a .lower() and then counting might involve two passes of the same string.

Thread Thread
pbouillon profile image
Pierre Bouillon

I suggested it to reduce your conditions, lowering the string before checking would have allowed you to only check for o and x for example. This way you would have one pass on the string and a more concise condition :)

Thread Thread
ganeshtata profile image
Tata Ganesh

Do you mean lowering the string before the loop or lowering the character in the loop before checking whether it is an 'x' or 'o'?

  • Lowering the string before the loop would involve one complete pass of the string. And then you would have to iterate through the string, again, to count the frequencies.
  • Lowering just the character inside the loop, is just equivalent to the if condition, right? I am probably saving on a function call by not calling .lower() on the character.
Thread Thread
pbouillon profile image
Pierre Bouillon

Oh right, nevermind !

Collapse
oskarlarsson profile image
Oskar Larsson

In Haskell, with what I thought was kind of a neat method:

import Data.Char

val 'x' = 1
val 'o' = -1
val other = 0

check str
 | (sum $ map (val . toLower) str) == 0 = True
 | otherwise = False

As a javascript one-liner:

string.toLowerCase().split('').map(a => a == 'x' ? 1 : a == 'o' ? -1 : 0).reduce((acc, a) => acc+a) == 0 ? true : false
Collapse
kip13 profile image
kip

A simple solution with Rust.

fn main() {
    println!(
        "{} the same amount",
        if has_same_amount("$XxkkLLOoox-", "x", "o") {
            "Has"
        } else {
            "Not has"
        }
    )
}

fn has_same_amount(str: &str, ch1: &str, ch2: &str) -> bool {
    let str = str.to_lowercase();

    str.matches(ch1).count() == str.matches(ch2).count()
}
Has the same amount
Collapse
pbouillon profile image
Pierre Bouillon

Python to the rescue !

def dev(inp: str) -> bool:
    return inp.lower().count('x') == inp.lower().count('o')

output

>>> dev('xoxo')
True
>>> dev('xaabboccddxeeffo')
True
>>> dev('x')
False
>>> dev('ooooox')
False
Collapse
bgadrian profile image
Adrian B.G.

Time for a Go kata you say?


func IsBalanced(dic map[rune]int, s string) bool {
        b := 0
        for _, r := range strings.ToLower(s) {
            i, ok := dic[r]
            if ok == false {
                continue
            }
            b += i
        }
        return b == 0
    }   

func main() {
    //because the world is bigger than Latin
    var step = map[rune]int{'x': 1, '🗴': 1, 'o': -1, 'ອ': -1}
    table := map[string]bool{
        "":true, //0x == 0o
        "x0x0": true,
        "ອXອXອ":  false,
        "H🗴H🗴H(╯° °)╯︵ ┻━┻)HoHo":true,
    }

    for input, exp := range table {
        fmt.Printf("'%s', exp: '%v', got: '%v'\n", input, exp, IsBalanced(step, input))
    }

}


play.golang.org/p/n8q9BYrsW4a

Collapse
jay profile image
Jay

Rust Solution.

fn check_x_o(s: &str) -> bool {
  s.to_lowercase()
    .chars()
    .map(|c| match c {
      'x' => 1,
      'o' => -1,
      _ => 0,
    })
    .sum::<i32>() == 0
}

// Usage
fn main() {
  let st = "xoxABCxo";
  println!("{}", check_x_o(&st));    // false
}
Collapse
coreyja profile image
Corey Alexander

Ruby Solution!

def character_counts(str)
  str.chars.each_with_object(Hash.new(0)) { |char, hash| hash[char] += 1 }
end

def check(str)
  str.downcase!
  char_count = character_counts(str)
  char_count['o'] == char_count['x']
end

irb(main):003:0> check('xoxo')
=> true
irb(main):004:0> check('xaabboccddxeeffo')
=> true
irb(main):005:0> check('x')
=> false
irb(main):006:0> check('ooooox')
=> false