DEV Community

Daily Challenge #47 - Alphabets

dev.to staff on August 22, 2019

In today's challenge, you are asked to replace every letter with its position in the alphabet for a given string where 'a' = 1, 'b'= 2, etc. For ...
Collapse
 
aminnairi profile image
Amin • Edited

JavaScript

My take at the challenge in JavaScript.

Source-Code

"use strict";

function lettersOnly(letterOrElse) {
  return letterOrElse.toUpperCase() !== letterOrElse.toLowerCase();
}

function toAlphabetPosition(letter) {
  return letter.toLowerCase().charCodeAt(0) - 'a'.charCodeAt(0) + 1;
}

function alphabet_position(input) {
  return Array
    .from(input)
    .filter(lettersOnly)
    .map(toAlphabetPosition)
    .join(" ");
}

const result = alphabet_position("The sunset sets at twelve o' clock.");
const expectations = "20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11";

assert(result === expectations); // undefined (meaning OK)

Test it yourself

Available online here.

Collapse
 
jasman7799 profile image
Jarod Smith

love how readable this is

Collapse
 
aminnairi profile image
Amin

Thank you sir!

Collapse
 
jasman7799 profile image
Jarod Smith
const alphaPosition = str => [...str]
  .filter(letter => letter.toLowerCase().charCodeAt(0) - 96 > 0)
  .map(letter => letter.toLowerCase().charCodeAt(0) - 96)
  .reduce((s, pos) => s += `${pos} `, '')
  .trim();

classic map filter reduce problem loved it.

Collapse
 
serbuvlad profile image
Șerbu Vlad Gabriel • Edited

x86_64 assembly (System V ABI, GNU assembler), as usual. Not really correct, since there will be an extra ' ' at the end which I was too lazy to remove, but it'll do.

alphabetic_position.S

    .global alphabetic_position

    .text
alphabetic_position:
    #using these registers to avoid sprintf breaking them
    push %rbx
    push %rbp

    mov %rdi, %rbx
    mov %rdi, %r12
    mov %rsi, %rbp

    xor %eax, %eax
    xor %edx, %edx
loop:
    mov (%rbp), %dl

    cmp $65, %dl # 'A'
    jl skip

    cmp $91, %dl # 'Z' + 1
    jl print

    cmp $97, %dl # 'a'
    jl skip

    cmp $123, %dl # 'z' + 1
    ja skip

printl:
    sub $32, %dl # 'a' -> 'A'
print:
    sub $64, %dl # 'A' -> 1

    push %rdx

    mov %rbx, %rdi
    mov $format, %rsi
    call sprintf

    add %rax, %rbx

    pop %rdx
skip:
    inc %rbp
    cmp $0, %dl
    jne loop

    mov %r12, %rax

    pop %rbp
    pop %rbx
    ret


    .section .rodata
format:
    .asciz "%d "

alphabetic_position.h:

char *alphabetic_position(char *dst, const char *src);

Edit: the function name now conforms to the specification, as well as with the "returns the string" requirement (by returning a copy of dst).

Collapse
 
hectorpascual profile image
Héctor Pascual

that's crazy

Collapse
 
tiash990 profile image
Tiash • Edited

In C++

#include <string>
#include <iostream>

void alphabet_position(std::string s) {
    for (int i = 0; i < s.size(); i++)
    {
        int pos = (int)((char)s[i] - 'a');
        pos = pos < 0 ? pos + ('a' - 'A') : pos;
        if (pos >= 0 && pos <= 'z' - 'a') {
            std::cout << pos+1 << " ";
        }
    }
}

int main (int argc, char *argv[])
{
    alphabet_position("<The quick brown fox jumps over the lazy dog!>");
    //print 20 8 5 17 21 9 3 11 2 18 15 23 14 6 15 24 10 21 13 16 19 15 22 5 18 20 8 5 12 1 26 25 4 15 7
    return 0;
}

Edited: there was a bug :D

Collapse
 
aadibajpai profile image
Aadi Bajpai

Python one liner to the rescue 🙂

print(*[ord(x.lower())-96 for x in input() if x.isalpha()])

Collapse
 
brightone profile image
Oleksii Filonenko • Edited

Rust:

pub fn alphabet_position(text: &str) -> String {
    text.to_lowercase()
        .chars()
        .filter(|c| c.is_alphabetic())
        .map(|char| (char as usize - 96).to_string())
        .collect::<Vec<String>>()
        .join(" ")
}

#[test]                                                                                        
fn test_alphabet_position() {                                                                  
    assert_eq!(                                                                                
        alphabet_position("The sunset sets at twelve o' clock."),                              
        String::from("20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11")
    );                                                                                         
}                                                                                              
Collapse
 
jasman7799 profile image
Jarod Smith

this has shown me how similar rust syntax can be to JavaScript syntax wow

Collapse
 
alvaromontoro profile image
Alvaro Montoro • Edited

JavaScript

const code = s => [...s].reduce((a, v) => v.match(/[a-z]{1}/i) 
                                          ? a+(v.toLowerCase().charCodeAt(0)-96)+' ' 
                                          : a
                        , '')
                        .trim();

And as an extra, the decoder:

const decode = s => String.fromCharCode(...s.split(' ').map(val=>parseInt(val) + 96));

Although the decoding process is not perfect, because all the spaces and symbols are lost during the coding process. For example, the sentence "The sunset sets at twelve o' clock" will be coded into:

"20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11"

Which will be decoded into:

"thesunsetsetsattwelveoclock"

Link to live demo.

Collapse
 
craigmc08 profile image
Craig McIlwrath
import Data.Maybe (catMaybes)
import Data.List (find)
import Data.Functor (fmap)
import Data.Char (toLower) 

alpha = ['a'..'z']

isAlpha :: Char -> Bool
isAlpha = (`elem` alpha)

(>.<) :: (a -> b -> d) -> (c -> b) -> (a -> c -> d)
a >.< b = flip $ flip a . b

toNumber :: Char -> Maybe Int
toNumber = fmap snd . (flip find) alphaNum . ((==) >.< fst)
  where alphaNum = zip alpha [1..]

encodeMsg :: String -> String
encodeMsg = unwords . map show . catMaybes . map toNumber . filter isAlpha . map toLower

I wanted to try to write this function completely using point-free style. It led to me having to write that >.< operator, which you can see from the type definition exactly what it does. It was a good mental exercise in types for me, a Haskell beginner.

Collapse
 
curtisfenner profile image
Curtis Fenner

You don't need your filter isAlpha and isAlpha functions, since toNumber already returns None when the character isn't a letter, which chops off a nice bit of the solution!

You can also use findIndex from Data.List instead of find-with-zip (though that solution is cool! 😋

toNumber = (fmap (+1)) . (flip findIndex alpha) . (==)
Collapse
 
matrossuch profile image
Mat-R-Such

Python

import string
def alphabet_position(text):
    text = [i for i in text.replace(' ','').lower() if i.isalpha() ]
    position = [str(string.ascii_lowercase.find(i)+1) for i in text ]
    return ' '.join(position)
Collapse
 
peter279k profile image
peter279k

Here is the simple solution with PHP:

function alphabet_position(string $s): string {
    $s = strtoupper($s);
    $alphabetNums = range(65, 90);
    $alphabets = [];

    foreach ($alphabetNums as $chr) {
        $aphabets[] = chr($chr);
    }

    $result = "";

    $index = 0;
    for (; $index < strlen($s); $index++) {
        if (in_array($s[$index], $aphabets) === false) {
            continue;
        }

        $result .= (string)(ord($s[$index]) - 64) . " ";
    }

    return substr($result, 0, -1);
}
Collapse
 
avalander profile image
Avalander

Haskell

Some function composition sorcery in Haskell.

import Data.Char (isLetter, toUpper, ord)

alphabet_position :: String -> String
alphabet_position = unwords . map (show . (flip (-)) 64 . ord . toUpper) . filter isLetter

Explanation

The . operator composes functions, so they will be applied from right to left.

  1. filter isLetter will remove all characters that are not letters from the string.
  2. map (show . (flip (-)) 64 . ord . toUpper) Transforms each character to its position in the alphabet.
    1. toUpper transforms the character to uppercase, so that we can substract 64 from it's code to know the position.
    2. ord maps a character to its ASCII code.
    3. (flip (-) 64) subtracts 64 from the character code. Since the code for 'A' is 65, this will give us the position in the alphabet starting at index 1. The way it works is it partially applies the second argument of the subtract operator to 64, i.e., this is equivalent to (\x -> x - 64) but fancier.
    4. show maps any type deriving from Show (Int in this case) to String.
  3. unwords joins a list of strings using space as a separator.
Collapse
 
celyes profile image
Ilyes Chouia • Edited

a bit late but here's the answer anyway... in PHP

function alphabet_position($text){
    $alphabet = range('a', 'z');     
    $strippedText = str_split(strtolower(preg_replace("/[^a-zA-Z]/", "", $text)));   
    $result = "";
    foreach($strippedText as $letter){
        $result .= array_search($letter, $alphabet)+1 . " ";   
    }
    return $result;
}
echo alphabet_position("The sunset sets at twelve o' clock.");
Collapse
 
curtisfenner profile image
Curtis Fenner • Edited

Lua, just as a series of string operations:

local function solution(text)
    return text:lower()
        :gsub("%A+", "")
        :gsub("%a", function(n) return " " .. 1 + n:byte() - string.byte("a") end)
        :sub(2)
end

Lua, written with a loop and so a bit less wasteful:

local function solution(text)
    local ns = {}
    for a in text:gmatch("%a") do
        table.insert(ns, 1 + a:lower():byte() - string.byte("a"))
    end
    return table.concat(ns, " ")
end
Collapse
 
yas46 profile image
Yasser Beyer • Edited

JavaScript

let position = (str) => {
    const upper = str.trim().toUpperCase().split('');
    let arr = [];
    upper.map(l => (/^[a-z]+$/i.test(l)) && arr.push(l.charCodeAt(0)-64).toString())
    return arr.join(" ");
}

position("The sunset sets at twelve o' clock.");
Collapse
 
willsmart profile image
willsmart • Edited

A JS one-liner

alphaPosition = s => [...s.toLowerCase().replace(/[^a-z]/g, '')].map(c => c.charCodeAt(0) + 1 - 'a'.charCodeAt(0)).join(' ');

Output:

> alphaPosition("The sunset sets at twelve o' clock.")
< "20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11"
Collapse
 
jesseleite profile image
Jesse Leite

In PHP using Laravel's Collection pipeline...

function alphabetPositions($string)
{
    return collect(str_split($string))
        ->map(function ($letter) {
            return collect(range('a', 'z'))->flip()->get(strtolower($letter));
        })
        ->filter()
        ->map(function ($key) {
            return $key + 1;
        })
        ->implode(' ');
}

echo alphabetPositions("The sunset sets at twelve o' clock.");

Will be cleaner when PHP gets shorthand arrow functions, which I believe are coming in 7.4 😍 ...

function alphabetPositions($string)
{
    return collect(str_split($string))
        ->map(fn($letter) => collect(range('a', 'z'))->flip()->get(strtolower($letter)))
        ->filter()
        ->map(fn($key) => $key + 1)
        ->implode(' ');
}

echo alphabetPositions("The sunset sets at twelve o' clock.");
Collapse
 
5422m4n profile image
Sven Kanoldt

solved in rust made with tests first :)

pub fn alphabet_position(s: &str) -> String {
  s.to_lowercase()
    .chars()
    .filter(|x| x.is_alphabetic())
    .map(|x| -> u8 { x as u8 - 'a' as u8 + 1 })
    .map(|x| -> String { x.to_string() })
    .collect::<Vec<String>>()
    .join(" ")
}

#[cfg(test)]
mod test {
  use super::*;

  #[test]
  fn it_should_relace_the_a_with_1() {
    let replaced = alphabet_position("a");
    assert_eq!(replaced, "1");
  }

  #[test]
  fn it_should_relace_the_capital_a_with_1() {
    let replaced = alphabet_position("A");
    assert_eq!(replaced, "1");
  }

  #[test]
  fn it_should_ignore_non_characters() {
    let replaced = alphabet_position("'a a. 2");
    assert_eq!(replaced, "1 1");
  }

  #[test]
  fn it_should_relace_the_sentence() {
    let replaced = alphabet_position("The sunset sets at twelve o' clock.");
    assert_eq!(
      replaced,
      "20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11"
    );
  }
}
Collapse
 
choroba profile image
E. Choroba • Edited

Perl solution:

#!/usr/bin/perl
use warnings;
use strict;

sub alphabet_position {
    join ' ', map ord() - 96, grep /[a-z]/, split //, lc shift
}

use Test::More tests => 1;

is alphabet_position("The sunset sets at twelve o' clock."),
    '20 8 5 19 21 14 19 5 20 19 5 20 19 1 20 20 23 5 12 22 5 15 3 12 15 3 11';

Reading from the right: shift gets the argument, lc lower-cases it, split using an empty regex splits it into characters, grep removes all non-letters, ord returns the ASCII ordinal number of each letter, 97 corresponds to a; map replaces the characters by the numbers, join connects the numbers back to a string.

See join, map, ord, grep, split, lc, shift.

Collapse
 
hanachin profile image
Seiei Miyagi • Edited

ruby <3

def alphabet_position(s)
  pos = (?a..?z |> zip 1..26 |> to_h)
  s |> downcase |> scan /[a-z]/ |> map &pos |> join ' '
end
Collapse
 
ryder_flynn profile image
Danish Flynn

"One-liner" (kind of) Ruby:

def alphabet_position(str)
  str.downcase.split('').select { |c| c =~ /[a-z]/ }.map { |c| c.ord - 96 }.join(' ')
end
Collapse
 
rione94 profile image
liễu nguyễn
def alphabet_position(str)
  str.downcase.gsub(/[^a-z]/, '').split('').map{|c| c.ord - 96}.join(' ')
end
Collapse
 
andre000 profile image
André Adriano

My take on this challenge, with Javascript

const encode = str => [...str.toLowerCase().replace(/[^a-z]/g, '')]
        .map(ch => ch.charCodeAt() - 96)
        .join(' ');

Collapse
 
jasman7799 profile image
Jarod Smith

so simple love it

Collapse
 
alfredosalzillo profile image
Alfredo Salzillo

One line Javascript

const alphaPosition = str => [...str]
  .filter(letter => /[a-zA-Z]/.test(letter))
  .map(letter => letter.toLowerCase().charCodeAt(0) - 96)
  .join(' ')
Collapse
 
b2aff6009 profile image
b2aff6009

A tiny python solutiuon:

def alphabet_position(text):
    converted = [str(ord(c) - ord('a') + 1) for c in text.lower() if c >= 'a']
    return " ".join(converted)
Collapse
 
sonugan profile image
sonugan

C#

public static string AlphabetPosition(string text)
{
   return string.Join(" ", text
    .ToLower()
    .Where(c => char.IsLetter(c))
    .Select(c => (c - 'a') + 1)
    .ToList());
}
Collapse
 
devparkk profile image
Dev Prakash
Collapse
 
hectorpascual profile image
Héctor Pascual

Python :

lambda s : ' '.join([str(ord(c)-ord('a')+1) for c in s.lower() if re.search('[a-z]',c)])
Collapse
 
alexkhismatulin profile image
Alex Khismatulin
function alphabetPosition(text) {
  return text.toUpperCase().replace(/[^A-Z]/g, '').replace(/[A-Z]/g, str => str.charCodeAt() - 64 + ' ').trim();
}