Solução dos exercícios do capítulo 8 - Strings

Exercício 8-1

Escreva uma função que recebe uma string como argumento e mostra as letras na ordem contrária, uma por linha


function letrasreverso(s)
    i = lastindex(s)
    while i > 0
        println(s[i])
        i = prevind(s, i)
    end
end
julia> letrasreverso("paulo")
o
l
u
a
p

julia> letrasreverso("áéíóú")
ú
ó
í
é
á

Exercício 8-2

Realmente não entendi o que se quer aqui…

Exercício 8-3

str[:] é simplesmente fatiar a string do começo ao fim

julia> s = "Esta é uma string tosca"
"Esta é uma string tosca"

julia> s[1]
'E': ASCII/Unicode U+0045 (category Lu: Letter, uppercase)

julia> s[:]
"Esta é uma string tosca"

julia> s[begin:end]
"Esta é uma string tosca"

Exercício 8-4

function find(word, letter, index)
    
    while index <= sizeof(word)
        if word[index] == letter
            return index
        end
        index = nextind(word, index)
    end
    return -1
    
end

Uso:

julia> find("palavra", 'a', 1)
2

julia> find("palavra", 'v', 1)
5

julia> find("palavra", 'r', 1)
6

julia> find("palavra", 'z', 1)
-1

Exercício 8-5

function count(word, letter)

    counter = 0
    for c in word
        if c == letter
            counter += 1
        end
    end
    return counter
end

Exemplo:

julia> count("palavra", 'p')
1

julia> count("palavra", 'a')
3

julia> count("palavra", 'z')
0

Exercício 8-6

Programa original corrigido:

function isreverse(word1, word2)
    if length(word1) != length(word2)
        return false
    end
    i = firstindex(word1)
    j = lastindex(word2)
    while j > 0
        if word1[i] != word2[j]
            return false
        end
        j = prevind(word2, j)
        i = nextind(word1, i)
    end
    true
end

Dois problemas no programa original

  • Atualizava j antes de comparar
  • Condição j >= 0 deveria ser j > 0 com a correção anterior.

Exercício 8-7

Cada um tem que fazer isso…

Exercício 8-8

Para ativar o help, digite ?:

help?> count
search: count count! codeunit conj const round cot ismount codeunits copyuntil

  count([f=identity,] itr; init=0) -> Integer

  Count the number of elements in itr for which the function f returns true.
  If f is omitted, count the number of true elements in itr (which should be
  a collection of boolean values). init optionally specifies the value to
  start counting from and therefore also determines the output type.

  │ Julia 1.6
  │
  │  init keyword was added in Julia 1.6.

  See also: any, sum.

  Examples
  ≡≡≡≡≡≡≡≡

  julia> count(i->(4<=i<=6), [2,3,4,5,6])
  3
  
  julia> count([true, false, true, true])
  3
  
  julia> count(>(3), 1:7, init=0x03)
  0x07

  ──────────────────────────────────────────────────────────────────────────

  count(
      pattern::Union{AbstractChar,AbstractString,AbstractPattern},
      string::AbstractString;
      overlap::Bool = false,
  )

  Return the number of matches for pattern in string. This is equivalent to
  calling length(findall(pattern, string)) but more efficient.

  If overlap=true, the matching sequences are allowed to overlap indices in
  the original string, otherwise they must be from disjoint character
  ranges.

  │ Julia 1.3
  │
  │  This method requires at least Julia 1.3.

  │ Julia 1.7
  │
  │  Using a character as the pattern requires at least Julia 1.7.

  Examples
  ≡≡≡≡≡≡≡≡

  julia> count('a', "JuliaLang")
  2
  
  julia> count(r"a(.)a", "cabacabac", overlap=true)
  3
  
  julia> count(r"a(.)a", "cabacabac")
  2

  ──────────────────────────────────────────────────────────────────────────

  count([f=identity,] A::AbstractArray; dims=:)

  Count the number of elements in A for which f returns true over the given
  dimensions.

  │ Julia 1.5
  │
  │  dims keyword was added in Julia 1.5.

  │ Julia 1.6
  │
  │  init keyword was added in Julia 1.6.

  Examples
  ≡≡≡≡≡≡≡≡

  julia> A = [1 2; 3 4]
  2×2 Matrix{Int64}:
   1  2
   3  4
  
  julia> count(<=(2), A, dims=1)
  1×2 Matrix{Int64}:
   1  1
  
  julia> count(<=(2), A, dims=2)
  2×1 Matrix{Int64}:
   2
   0

Esta função é bem genérica e tem várias versões. Alguns exemplos de uso:

julia> count('a', "banana")
3

julia> count(==('a'), "banana")
3

Exercício 8-9

julia> fruit = "banana"
"banana"
julia> fruit[1:2:6]
"bnn"

Usando indexação com passo de -1:

ispalindrome(s) = s == s[end:-1:1]
julia> ispalindrome("aeiea")
true

Cuidado! Esta função só funciona com caracteres ASCII.

julia> ispalindrome("áeieá")
ERROR: StringIndexError: invalid index [2], valid nearby indices [1]=>'á', [3]=>'e'
Stacktrace:
 [1] string_index_err(s::String, i::Int64)
   @ Base ./strings/string.jl:12
 [2] getindex_continued(s::String, i::Int64, u::UInt32)
   @ Base ./strings/string.jl:472
 [3] getindex
   @ ./strings/string.jl:464 [inlined]
 [4] (::Base.var"#451#452"{String, StepRange{Int64, Int64}})(io::IOBuffer)
   @ Base ./strings/basic.jl:193
 [5] sprint(::Function; context::Nothing, sizehint::Int64)
   @ Base ./strings/io.jl:114
 [6] sprint
   @ ./strings/io.jl:107 [inlined]
 [7] getindex
   @ ./strings/basic.jl:192 [inlined]
 [8] ispalindrome(s::String)
   @ Main ./REPL[13]:1
 [9] top-level scope
   @ REPL[15]:1

Porque?

Exercício 8-10

function anylowercase1(s)
    for c in s
        if islowercase(c)
            return true
        else
            return false
        end
    end
end

Esta função vai retornar true se a primeira letra for minúscula, false se for maiúscula. Ainda existe um outro caso de um string vazio "" e neste caso, a função retorna nothing

function anylowercase2(s)
    for c in s
        if islowercase('c')
            return "true"
        else
            return "false"
        end
    end
end

Esta função retorna true para todos os casos pois c é minúscula. A única exceção é quando a string é vazia "". Neste caso a função retorna nothing.


function anylowercase3(s)
    for c in s
        flag = islowercase(c)
    end
    flag
end

Esta função vai sempre resultar em erro caso não exista uma variável global flag. A variável flag dentro do laço for é uma variável local! Então flag só pode estar definida fora do corpo da função o que não é algo que a gente quer (neste caso) ou recomenda (em geral).

function anylowercase4(s)
    flag = false
    for c in s
        flag = flag || islowercase(c)
    end
    flag
end

Esta função parece estar correta. Mas vai percorrer toda a string mesmo que não precise. Achou uma letra minúscula, pode retornar verdadeiro.

function anylowercase5(s)
    for c in s
        if !islowercase(c)
            return false
        end
    end
    true
end

Esta função não funciona pois no momento que achar uma letra que não é minúscula, ela retorna false mesmo que existam letras minúsculas mais para frente.

Exercício 8.11

Vou fazer uma função rotatechar que faz a operação para uma letra. Depois implemento a função rotateword que aplica a função para todas as letras.

Algo que deve ser notado é que n pode ser qualquer número inteiro (positivo ou negativo, um número enorme, etc) e o programa deve considerar letras maiúsculas ou minúsculas.

O programa aqui só funciona com letras ASCII (‘a’-‘z’ e ‘A’-‘Z’).

function rotatechar(c, n)
    
    if islowercase(c)
        ia0 = Int('a')
    elseif isuppercase(c)
        ia0 = Int('A')
    end

    idx = (Int(c) - ia0 + n) % 26
    if idx < 0
        idx += 26
    end
    

    return Char(ia0 + idx)
end


function rotateword(w,n)
    s = ""
    for c in w
        s = s * rotatechar(c,n)
    end
    return s
end

Exemplo:

julia> rotateword("cheer", 7)
"jolly"

julia> rotateword("CHEER", 7)
"JOLLY"

julia> rotateword("CHeer", 7)
"JOlly"

julia> rotateword("HAL", 1)
"IBM"

julia> rotateword("hal", 1)
"ibm"

julia> rotateword("Hal", 1)
"Ibm"

julia> rotateword("melon", -10)
"cubed"

julia> rotateword("Melon", -10)
"Cubed"