DEV Community

José Oscátegui
José Oscátegui

Posted on

Check if the chain has the same amount

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.

Top comments (12)

Collapse
 
ganeshtata profile image
Tata Ganesh • Edited

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 • Edited

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 • Edited

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