DEV Community

Daily Challenge #244 - Search for Letters

dev.to staff on May 19, 2020

Create a function which accepts one arbitrary string as an argument, and return a string of length 26. The objective is to set each of the 26 chara...
Collapse
 
iamhrithikraj profile image
Hrithik Raj • Edited

C++17


#include<bits/stdc++.h>
using namespace std;
int main() {
    string str;
    vector<int>vec(26, 0);
    getline(cin, str);
    transform(str.begin(), str.end(), str.begin(), ::tolower);
    for (auto i = str.begin(); i != str.end(); ++i) {
        if (isalpha(*i)) {
            vec[*i - 'a'] = 1;
        }
    }
    for (auto i = vec.begin(); i != vec.end(); ++i) {
        cout << *i;
    }

}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
miketalbot profile image
Mike Talbot ⭐ • Edited

This is a one statement in JS that works:

    (input)=>input.match(/[a-zA-Z]/g)
        .reduce((c,a)=>(c[(a.charCodeAt(0) & 31) -1]='1',c), 
           Array.from('0'.repeat(26)))
       .join('')
Collapse
 
vidit1999 profile image
Vidit Sarkar • Edited

Here is a C++ solution,

string change(string s){
    string st(26, '0');

    for(char c : s)
        if(islower(c) || isupper(c))
            st[tolower(c)-'a'] = '1';

    return st;
}
Collapse
 
qm3ster profile image
Mihail Malo • Edited

Rust

yay fun with bitsets

fn change(hay: &str) -> String {
    let mut output = 0u32;
    for c in hay.chars() {
        match c {
            'a'..='z' => output |= 1u32 << (b'z' - c as u8),
            'A'..='Z' => output |= 1u32 << (b'Z' - c as u8),
            _ => {}
        }
    }
    format!("{:026b}", output)
}

// "Test"

fn main() {
    assert_eq!(change("a **& cZ"), "10100000000000000000000001");
    assert_eq!(change("Abc e $$ z"), "11101000000000000000000001");

    let c = |x| println!(r#"{} <= "{}""#, change(x), x);
    // "Tests"
    c("!!a$%&RgTT");
    c("");
    c("abcdefghijklmnopqrstuvwxyz");
    c("aaaaaaaaaaa");
}

On infinitely long strings it would be good to:

  1. Shrink the range when high or low characters already matched
  2. Return early if we achieve 0b11111111111111111111111111

but on such short strings these would both be slower

Edit:

I have stolen the ascii case sensitivity bit from @miketalbot and will now proceed to pleasure myself with this fish

fn change(hay: &str) -> String {
    let mut output = 0u32;
    for c in hay.chars() {
        if let c @ b'A'..=b'Z' = c as u8 & 0b11011111 {
            output |= 1u32 << (b'Z' - c)
        }
    }
    format!("{:026b}", output)
}

Is this actually faster?
No idea.
Alternatively

if let c @ b'A'..=b'Z' | c @ b'a'..=b'z' = c as u8 {
    output |= 1u32 << (b'Z' - (c & 0b11011111))
}

or even just

if matches!(c, 'A'..='Z' | 'a'..='z') {
    output |= 1u32 << (b'Z' - (c as u8 & 0b11011111))
}

🤷

Collapse
 
agtoever profile image
agtoever • Edited

Python 3.7

# solution
import string
change = lambda s: "".join(['1' if c in s.lower() else '0' for c in string.ascii_lowercase])

# testcases
for case in ["!!a$%&RgTT", "", "abcdefghijklmnopqrstuvwxyz", "aaaaaaaaaaa"]:
    print(f"change({case}) = {change(case)}")

Try it online!

(Sorry. I didn’t manage for format the code in markdown properly on my iphone)

Collapse
 
peritract profile image
Dan Keefe

I had roughly the same idea:

def isin(text):
  text = text.lower()
  return "".join([str(1)
                  if letter in text
                  else str(0)
                  for letter in "abcdefghhijklmnopqrstuvwxyz"])
Collapse
 
capecodconnor profile image
connormaher92 • Edited

Here is a Ruby solution

def change(str)
  result = '0' * 26
  str = str.downcase
  str.each_char do |char|
    result[(char.ord - 97)] = '1' if char.ord.between?(97, 122)
  end
  result
end
Collapse
 
peter279k profile image
peter279k

Here is the Python solution:

def change(st):
    answer_string = [
        '0','0','0','0','0','0','0','0','0','0','0','0','0',
        '0','0','0','0','0','0','0','0','0','0','0','0','0',
    ]

    upper_alphabets = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

    for char in st:
        upper_index = 0
        for upper_alphabet in upper_alphabets:
            if upper_alphabet == char or upper_alphabet.lower() == char:
                answer_string[upper_index] = '1'
            upper_index += 1

    return "".join(answer_string)
Collapse
 
mattymaloney profile image
mattymaloney • Edited
const countEm = (str) => {
  str = str.toLowerCase();
  return 'abcdefghijklmnopqrstuvwxyz'.split('').map((letter) => {
    return str.indexOf(letter) === -1 ? '0' : '1';
  }).join('')
};

Thanks for the challenge!

Collapse
 
qm3ster profile image
Mihail Malo

There's also String.prototype.includes

const letters = "abcdefghijklmnopqrstuvwxyz".split("")
const countEm = str => {
  str = str.toLowerCase()
  return letters.map(letter => str.includes(letter) ? "0" : "1").join("")
}
Collapse
 
capecodconnor profile image
connormaher92

Thanks Michael, I like that better.