Ir para o conteúdo
thoga31

[Muito fácil] Interpretar um pequeno ficheiro

Mensagens Recomendadas

thoga31

Este desafio tem como principal público-alvo os principiantes ou, porventura, aqueles que estão a começar a estudar uma nova LP. ;)

Objectivo: O desafio é simples: abrir um ficheiro e interpretar, por linha, apenas o primeiro caracter se e só se este for um dígito ou uma letra minúscula. No final, dever-se-á fazer o output da soma dos dígitos e o nº de vezes que cada letra apareceu (o output não deverá conter as letras que nunca apareceram).

Exemplo I/O:

Ficheiro:

5
alegria
n
7
4
n
654321
1
007
yes!
woow
atchim

Output:

Sum = 23
'a' = 2
'n' = 2
'w' = 1
'y' = 1

Editado por thoga31

Knowledge is free!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pwseo

Aqui vai uma tentativa, em Haskell. Ainda estou a aprender a mexer com Monads e Arrows, por isso é natural que haja formas mais legíveis e compactas de resolver o problema.

De qualquer modo, o principal é mesmo a função run, o resto é basicamente IO e imports.

import Data.Char
import Control.Arrow
import Control.Monad.State
import qualified Data.Map as M

type StateType = (Int, M.Map Char Int)

initState :: StateType
initState = (0, M.empty)

run :: [string] -> State StateType ()
run ls = mapM_ aux ls
 where
   aux (c:_) | isDigit c = modify $ first (+ (read [c]))
             | isLower c = modify $ second (M.insertWith (+) c 1)
             | otherwise = return ()

main :: IO ()
main = do
 input <- getInput
 let (s, m) = execState (run input) initState
 putStrLn $ "Sum = " ++ show s
 mapM_ (putStrLn . f) $ M.toList m
 where
   getInput = liftM lines $ getContents
   f (k,v) = show k ++ " = " ++ show v

EDIT: Alterei o código para algo que gostei mais, visualmente.

EDIT2: Aceitar apenas dígitos e letras minúsculas

Editado por pwseo

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

@pwseo, tu conseguiste dar a volta ao problema de uma forma bastante complexa (do ponto de vista "mais comum"). Monads? Arrows? States? :D

Contudo, é uma solução bastante interessante do ponto de vista haskelliano, sem dúvida.

Só uma coisa: onde colocaste a condição de só serem permitidas letras minúsculas? Eu vejo a condição para os dígitos, mas não vejo o resto. De cabeça, se eu tiver uma linha a começar por "A", ele adiciona ao Map este caracter, e ele devia ser ignorado, assim como símbolos (!@#%...)

Bom, eu decidi desenferrujar todos os meus conhecimentos básicos, e aqui vão as linguagens em que pelo menos cujas bases eu conheço... :D

main :: IO()
main = do
 contents <- readFile "desafio.txt"
 putStrLn $ solveit contents

solveit = solve Map.empty 0 . map (head) . words
  where
    solve :: Map.Map Char Int -> Int -> String -> String
    solve alpha sumdig [] = "Sum = " ++ (show sumdig) ++ "\n" ++ (unlines . map (\(x,y) -> show x ++ " = " ++ show y) $ Map.toList alpha)
    solve alpha sumdig (x:xs) | Char.isLower x = case Map.lookup x alpha of
                                                   Just n  -> solve (Map.insert x (n+1) alpha) sumdig xs
                                                   Nothing -> solve (Map.insert x 1 alpha) sumdig xs
                              | Char.isDigit x = solve alpha (Char.digitToInt x + sumdig) xs
                              | otherwise      = solve alpha sumdig xs

def solveit(file_name = "desafio.txt"):
    f = open(file_name, "r")
    contents = [i[0] for i in f.readlines() if (ord(i[0]) >= ord('a') or ord(i[0]) <= ord('z')) or (ord(i[0]) >= ord('0') or ord(i[0]) <= ord('9'))]
    f.close()
    sumdigit = 0
    alpha = [0 for i in range(26)]
    for i in contents:
        if ord(i) >= ord('0') and ord(i) <= ord('9'):
            sumdigit += int(i)
        else:
            alpha[ord(i) - ord('a')] += 1
    result = "Sum = {0}\n".format(sumdigit)
    for i in range(0,26):
        if alpha[i] != 0:
            result += "'{0}' = {1}\n".format(chr(i + ord('a')), alpha[i])
    return result

if __name__ == "__main__":
    print(solveit())
    input()  # pausa (para Windows)

program challenge9;
type TLowAlpha = 'a'..'z';
const LOWALPHA : set of char = ['a'..'z'];
      DIGITS : set of char = ['0'..'9'];
      FILE_NAME = 'desafio.txt';
var alpha : array[TLowAlpha] of byte = (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);
    i : TLowAlpha;
    sumdigit : smallint = 0;
    f : text;
    s : string = '';

begin
    assign(f, FILE_NAME);
    reset(f);
    while not eof(f) do begin
        readln(f, s);
        if s[1] in DIGITS then
            inc(sumdigit, ord(s[1]) - ord('0'))
        else if s[1] in LOWALPHA then
            inc(alpha[s[1]]);
    end;
    close(f);
    writeln('Sum = ', sumdigit);
    for i := 'a' to 'z' do
        if alpha[i] <> 0 then
            writeln(i, ' = ', alpha[i]);
    readln;  // pausa
end.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#define MAX_STR 2
#define ALPHA_LEN 26

int main(void) {
    short int sumdigit = 0;
    short int alpha[ALPHA_LEN] = {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};
    char s[2];
    int i;
    FILE *f;
    
    f = fopen("desafio.txt", "r");
    while (fscanf(f, "%s", s) != EOF) {
        if (isdigit(s[0])) sumdigit += (short) s[0] - (short) '0';
        else if (isalpha(s[0]))
                if (islower(s[0])) alpha[(short) s[0] - (short) 'a']++;
    }
    fclose(f);
    
    printf("Sum = %hd\n", sumdigit);
    for(i=0; i < ALPHA_LEN; i++) {
        if (alpha[i] != 0)
            printf("%c = %hd\n", (char) (i + (short) 'a'), alpha[i]);
    }
    getchar();  /* pausa, só mais para o Windows */
}

Module Module1
    Sub Main()
        Dim file_name As String = "desafio.txt"
        Dim f As New IO.StreamReader(file_name)
        Dim ch As Char
        Dim sumdigit As UInt16 = 0
        Dim alpha() As UInt16 = {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}

        While Not f.EndOfStream
            ch = f.ReadLine()(0)
            If Char.IsDigit(ch) Then
                sumdigit += Convert.ToInt16(ch)
            ElseIf Char.IsLetter(ch) AndAlso Char.isLower(ch) Then
                alpha(Asc(ch) - Asc("a"c)) += 1
            End If
        End While

        Console.WriteLine("Sum = {0}", sumdigit)
        For i As UInt16 = 0 To alpha.Length - 1
            If alpha(i) <> 0 Then
                Console.WriteLine("'{0}' = {1}", Chr(i + Asc("a"c)), alpha(i))
            End If
        Next

        Console.ReadKey(True)
    End Sub
End Module


Knowledge is free!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
pwseo

Estava distraído, não reparei nessa restrição (como o teste que tinhas dado tinha o output correcto no meu caso, não reparei). Mas basta adicionar o ramo correspondente ao código...

Quanto à minha solução, apesar de "teoricamente complexa" se reparares está muito legível, pelo menos na minha opinião :) Temos uma função que claramente trata do algoritmo por detrás do problema e deixamos a apresentação do resultado toda para a main.

EDIT: Alterei o código.

Editado por pwseo

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites
thoga31

Quanto à minha solução, apesar de "teoricamente complexa" se reparares está muito legível, pelo menos na minha opinião :) Temos uma função que claramente trata do algoritmo por detrás do problema e deixamos a apresentação do resultado toda para a main.

Pois, como eu ainda não sou propriamente um especialista em Haskell e no tratamento I/O de dados, deixei a apresentação para a própria função que assim devolve uma String. Mas de facto não será nada difícil adaptar a main para receber os dados de outra forma e tratá-los. Mas agora fica assim, já há soluções em Haskell de sobra. :D


Knowledge is free!

Partilhar esta mensagem


Ligação para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora

×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.