exercism / vimscript

Exercism exercises in Vim script.
https://exercism.org/tracks/vimscript
MIT License
20 stars 24 forks source link

Building a training set of tags for vimscript #187

Closed ErikSchierboom closed 9 months ago

ErikSchierboom commented 10 months ago

Hello lovely maintainers :wave:

We've recently added "tags" to student's solutions. These express the constructs, paradigms and techniques that a solution uses. We are going to be using these tags for lots of things including filtering, pointing a student to alternative approaches, and much more.

In order to do this, we've built out a full AST-based tagger in C#, which has allowed us to do things like detect recursion or bit shifting. We've set things up so other tracks can do the same for their languages, but its a lot of work, and we've determined that actually it may be unnecessary. Instead we think that we can use machine learning to achieve tagging with good enough results. We've fine-tuned a model that can determine the correct tags for C# from the examples with a high success rate. It's also doing reasonably well in an untrained state for other languages. We think that with only a few examples per language, we can potentially get some quite good results, and that we can then refine things further as we go.

I released a new video on the Insiders page that talks through this in more detail.

We're going to be adding a fully-fledged UI in the coming weeks that allow maintainers and mentors to tag solutions and create training sets for the neural networks, but to start with, we're hoping you would be willing to manually tag 20 solutions for this track. In this post we'll add 20 comments, each with a student's solution, and the tags our model has generated. Your mission (should you choose to accept it) is to edit the tags on each issue, removing any incorrect ones, and add any that are missing. In order to build one model that performs well across languages, it's best if you stick as closely as possible to the C# tags as you can. Those are listed here. If you want to add extra tags, that's totally fine, but please don't arbitrarily reword existing tags, even if you don't like what Erik's chosen, as it'll just make it less likely that your language gets the correct tags assigned by the neural network.


To summarise - there are two paths forward for this issue:

  1. You're up for helping: Add a comment saying you're up for helping. Update the tags some time in the next few days. Add a comment when you're done. We'll then add them to our training set and move forward.
  2. You not up for helping: No problem! Just please add a comment letting us know :)

If you tell us you're not able/wanting to help or there's no comment added, we'll automatically crowd-source this in a week or so.

Finally, if you have questions or want to discuss things, it would be best done on the forum, so the knowledge can be shared across all maintainers in all tracks.

Thanks for your help! :blue_heart:


Note: Meta discussion on the forum

ErikSchierboom commented 10 months ago

Exercise: leap

Code

"
" This function takes a year and returns 1 if it's a leap year
" and 0 otherwise.
"
function! IsLeap(year) abort
  if a:year % 400 == 0
    return 1
  elseif a:year % 100 == 0
    return 0
  elseif a:year % 4 == 0
    return 1
  endif
endfunction

Tags:

No tags generated

ErikSchierboom commented 10 months ago

Exercise: hamming

Code

"
" This function takes two strings which represent strands and returns
" their Hamming distance.
"
" If the lengths of the strands don't match, throw this exception:
"
"     'The two strands must have the same length.'
"
function! Hamming(...)
  let [s1, s2] = map(copy(a:000), 'split(v:val,"\\zs")')
  if len(s1) != len(s2)
    throw 'The two strands must have the same length.'
  end
  return len(filter(range(len(s1)), 's1[v:val]!=s2[v:val]'))
endfunction

Tags:

construct:string
construct:assignment
construct:copy
construct:endfunction
construct:if
construct:indexing
construct:invocation
construct:let
construct:list
construct:map
construct:function
construct:parameter
construct:return
construct:string
construct:throw
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:reflective
technique:exceptions
technique:higher-order-functions
ErikSchierboom commented 10 months ago

Exercise: rna-transcription

Code

"
" This function takes a DNA strand and returns its RNA complement.
"
"   G -> C
"   C -> G
"   T -> A
"   A -> U
"
" If the input is invalid, return an empty string.
"
" Example:
"
"   :echo ToRna('ACGTGGTCTTAA')
"   UGCACCAGAAUU
"

let s:rna = {
\   'G':'C',
\   'C': 'G',
\   'T': 'A',
\   'A': 'U',
\}

function! ToRna(strand) abort
    let a:complement = ''
    for s:item in split(a:strand, '\zs')
        if s:item !~? '[GCTA]'
            return ''
        endif
        let a:complement.=s:rna[s:item]
    endfor
    return a:complement
endfunction

" echom ToRna('CTA')

Tags:

construct:assignment
construct:dictionary
construct:for-loop
construct:function
construct:if
construct:index
construct:invocation
construct:let
construct:loop
construct:return
construct:string
construct:variable
paradigm:imperative
paradigm:reflective
technique:looping
uses:Dictionary
ErikSchierboom commented 10 months ago

Exercise: anagram

Code

"
" Given a word and a list of possible anagrams, select the correct sublist.
"
" Hints:
"
"   - Same words don't match.
"   - Cases are treated insensitivley.
"   - The returned list is sorted.
"
" Example:
"
"   :echo Anagram('foo', ['foo', 'bar', 'oof', 'Ofo'])
"   ['Ofo', 'oof']
"
function! Anagram(word, candidates) abort
  let key = 'join(sort(split(tolower(v:val),"\\zs")),"")'
  let cand = sort(copy(a:candidates))
  let keys = map(copy(cand), key)
  let [tofind] = map([a:word], key)
  let ret = []
  for i in range(len(cand))
    if keys[i] == tofind && tolower(cand[i]) != tolower(a:word)
      cal add(ret, cand[i])
    end
  endfor
  return ret
endfunction

Tags:

construct:boolean
construct:assignment
construct:backslash
construct:boolean
construct:call
construct:copy
construct:double
construct:endif
construct:for-loop
construct:function
construct:if
construct:implicit-conversion
construct:indexing
construct:invocation
construct:lambda
construct:list
construct:logical-and
construct:map
construct:number
construct:parameter
construct:return
construct:string
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:boolean-logic
technique:higher-order-functions
technique:looping
uses:List
ErikSchierboom commented 10 months ago

Exercise: difference-of-squares

Code

"
" Find the difference between the square of the sum and the sum of the squares
" of the first N natural numbers.
"
" Examples:
"
"   :echo SquareOfSum(3)
"   36
"   :echo SumOfSquares(3)
"   14
"   :echo Difference(3)
"   22
"
function! Difference(number) abort
  return abs(SquareOfSum(a:number) - SumOfSquares(a:number))
endfunction

function! SquareOfSum(n) abort
  let ret = 0
  for i in range(a:n+1)
    let ret += i
  endfor
  return ret * ret
endfunction

function! SumOfSquares(n) abort
  let ret = 0
  for i in range(a:n+1)
    let ret += i * i
  endfor
  return ret
endfunction

Tags:

construct:add
construct:assignment
construct:comment
construct:for-loop
construct:function
construct:function-definition
construct:invocation
construct:let
construct:multiline-string
construct:number
construct:parameter
construct:return
construct:string
construct:subtract
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:functional
paradigm:object-oriented
technique:looping
ErikSchierboom commented 10 months ago

Exercise: difference-of-squares

Code

" Workaround for the fact that `range()` throws an error if it gets a negative
" number. I think it should just return an empty range.
function! Range(n)
  return a:n < 0 ? [] : range(a:n)
endfunction

" I can't believe I have to use `eval` for this...
function! Sum(numbers)
  return len(a:numbers) == 0 ? 0 : eval(join(a:numbers, ' + '))
endfunction

" Workaround for the fact that `pow()` returns a Float, which makes the tests
" fail because they don't use numerical equality.
function! Squared(n)
  return float2nr(pow(a:n, 2))
endfunction

"
" Find the difference between the square of the sum and the sum of the squares
" of the first N natural numbers.
"
" Examples:
"
"   :echo SquareOfSum(3)
"   36
"   :echo SumOfSquares(3)
"   14
"   :echo Difference(3)
"   22
"
function! Difference(number) abort
  return SquareOfSum(a:number) - SumOfSquares(a:number)
endfunction

function! SquareOfSum(number) abort
  return Squared(Sum(Range(a:number + 1)))
endfunction

function! SumOfSquares(number) abort
  return Sum(map(Range(a:number + 1), {i, n -> Squared(n)}))
endfunction

Tags:

construct:add
construct:boolean
construct:comment
construct:eval
construct:eval-in-vim
construct:expression
construct:float
construct:floating-point-number
construct:function
construct:function-overloading
construct:invocation
construct:lambda
construct:list
construct:map
construct:number
construct:parameter
construct:return
construct:subtract
construct:ternary
construct:using-a-float
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:reflective
technique:higher-order-functions
ErikSchierboom commented 10 months ago

Exercise: difference-of-squares

Code

"
" Find the difference between the square of the sum and the sum of the squares
" of the first N natural numbers.
"
" Examples:
"
"   :echo SquareOfSum(3)
"   36
"   :echo SumOfSquares(3)
"   14
"   :echo Difference(3)
"   22
"
function! Difference(number) abort
  let squareOfSum = SquareOfSum(a:number)
  let sumOfSquares = SumOfSquares(a:number)

  return squareOfSum - sumOfSquares
endfunction

function! SquareOfSum(number) abort
  let l:sum = s:sum(range(a:number + 1))

  return l:sum * l:sum
endfunction

function! SumOfSquares(number) abort
  return s:sum(map(range(a:number + 1), {i -> i * i}))
endfunction

function! s:sum(numbers) abort
  let l:sum = 0

  for n in a:numbers
    let l:sum += n
  endfor

  return l:sum
endfunction

Tags:

construct:add
construct:assignment
construct:comment
construct:dictionary
construct:for-loop
construct:function
construct:function-invocation
construct:invocation
construct:lambda
construct:let
construct:list
construct:local-variable
construct:map
construct:multiply
construct:number
construct:parameter
construct:return
construct:subtract
construct:variable
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:looping
ErikSchierboom commented 10 months ago

Exercise: raindrops

Code

"
" Convert a number to a string, the contents of which depend on the number's
" factors.
"
"   - If the number has 3 as a factor, output 'Pling'.
"   - If the number has 5 as a factor, output 'Plang'.
"   - If the number has 7 as a factor, output 'Plong'.
"   - If the number does not have 3, 5, or 7 as a factor, just pass
"     the number's digits straight through.
"
" Example:
"
"   :echo Raindrops(15)
"   PlingPlang
"
function! Raindrops(number) abort
  let output = ""

  if a:number % 3 == 0
    let output = output . 'Pling'
  endif

  if a:number % 5 == 0
    let output = output . 'Plang'
  endif

  if a:number % 7 == 0
    let output = output . 'Plong'
  endif

  if output == ''
    return str(a:number)
  endif

  return output
endfunction

Tags:

construct:string
construct:assignment
construct:comment
construct:endif
construct:function
construct:if
construct:implicit-conversion
construct:integral-number
construct:invocation
construct:let
construct:number
construct:parameter
construct:return
construct:string-concatenation
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
ErikSchierboom commented 10 months ago

Exercise: atbash-cipher

Code

"
" Create an implementation of the atbash cipher, an ancient encryption system
" created in the Middle East.
"
" Plain:  abcdefghijklmnopqrstuvwxyz
" Cipher: zyxwvutsrqponmlkjihgfedcba
"
" Examples:
"
"   :echo AtbashEncode('test')
"   gvhg
"
"   :echo AtbashDecode('gvhg')
"   test
"
"   :echo AtbashDecode('gsvjf rxpyi ldmul cqfnk hlevi gsvoz abwlt')
"   thequickbrownfoxjumpsoverthelazydog

function! Cypher_mapping() abort

    "create cypher mapping
    let l:alphabet = split("abcdefghijklmnopqrstuvwxyz", '\zs')
    let l:rvrs_alphabet = reverse(copy(l:alphabet))
    let l:comb_alphabet = {}
    for l:ind in range(len(l:alphabet))
    let l:comb_alphabet[l:alphabet[l:ind]] = l:rvrs_alphabet[l:ind]
    endfor  
    return l:comb_alphabet

endfunction

function! AtbashDecode(cipher) abort

    "define mapping
    let l:mapping = Cypher_mapping()

    "remove spacing between any grouping of letters
    let l:nsp_cipher = join(split(a:cipher), "")

    "loop through each letter and find the corresponding decoded mapping
    let dec_message = []
    for l:letter in split(l:nsp_cipher, '\zs')
    call add(dec_message, l:mapping[l:letter])
    endfor  
    let l:dec_message = join(l:dec_message, "")
    return l:dec_message

endfunction

function! AtbashEncode(plaintext) abort

    "define mapping
    let l:mapping = Cypher_mapping()

    "remove spacing between any grouping of letters
    let l:nsp_text = join(split(a:plaintext), "")

    "loop through each letter and find the corrsponding cypher mapping
    let l:inter_message = []
    for l:letter in split(l:nsp_text, '\zs')
    call add(l:inter_message, l:mapping[l:letter])
    endfor
    let l:inter_message = join(l:inter_message, "")

    "split encoded message into groupings of 5 ciphered letters
    let l:enc_message = ""
    for l:letter in range(len(l:inter_message)/5 + 1)
    let l:start = l:letter*5
    let l:end = l:letter*5 + (5-1)
    let l:enc_message = l:enc_message.l:inter_message[l:start : l:end]." "
    endfor

    return l:enc_message

endfunction

Tags:

construct:add
construct:assignment
construct:call
construct:dictionary
construct:divide
construct:for-loop
construct:function
construct:implicit-conversion
construct:indexing
construct:invocation
construct:lambda
construct:let
construct:list
construct:loop
construct:multiply
construct:number
construct:parameter
construct:return
construct:string
construct:subtract
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:looping
ErikSchierboom commented 10 months ago

Exercise: atbash-cipher

Code

func! s:lc_chars(str) abort
    return filter(split(tolower(a:str), '\zs'),
            \    'trim(v:val) =~? "\\w"')
endfunc

func! s:chunks(lst, size) abort
    let sub_list = []
    let res = []
    let i = 0
    let j = 0
    while i < len(a:lst)
        for j in range(0, (a:size - 1))
            call add(sub_list, get(a:lst, i + j, ''))
        endfor
        call add(res, sub_list)
        let sub_list = []
        let i += a:size
    endwhile
    return res
endfunc

let s:alphabet = map(range(97, 122), 'nr2char(v:val)')

func! AtbashDecode(cipher) abort
  let i = 0
  let charmap = {}
  for ch in reverse(copy(s:alphabet))
      let charmap[ch] = s:alphabet[i]
      let i += 1
  endfor
  return trim(join(map(s:lc_chars(a:cipher),
          \           'get(charmap, v:val, v:val)'),
          \       ''))
endfunc

func! AtbashEncode(plaintext) abort
  let i = 0
  let charmap = {}
  for ch in s:alphabet
      let charmap[ch] = reverse(copy(s:alphabet))[i]
      let i += 1
  endfor
  return trim(
          \ join(
          \   map(s:chunks(map(s:lc_chars(a:plaintext),
          \                   'get(charmap, v:val, v:val)'),
          \               5),
          \      'join(v:val, "")'),
          \  ' '))
endfunc

Tags:

construct:add
construct:assignment
construct:call
construct:dictionary
construct:for-loop
construct:func
construct:function
construct:if
construct:indexing
construct:invocation
construct:lambda
construct:let
construct:list
construct:method
construct:number
construct:parameter
construct:return
construct:string
construct:subtract
construct:variable
construct:visibility-modifiers
construct:while-loop
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:looping
uses:Dictionary
uses:List
ErikSchierboom commented 10 months ago

Exercise: phone-number

Code

"
" Clean up user-entered phone numbers so that they can be sent SMS messages.
"
" Example:
"
"   :echo ToNANP('+1 (613)-995-0253')
"   6139950253
"
"  (country code == 1)[1]? (area code)[3] (exchange code)[3] (subscriber number)[4]

function! ToNANP(number) abort
    if a:number =~ '\a' || (a:number[0] != '+' && a:number =~ '\V+') || a:number =~ '[^0-9 ().\-+]'
        return ''
    endif
    let number = substitute(a:number, '\D', '', 'g')
    if strlen(number) == 10
        let ret = number
    elseif strlen(number) == 11
        if number[0] == '1'
            let ret = number[1:]
        else
            return ''
        endif
    else
        return ''
    endif
    if ret[0] !~ '[2-9]' || ret[3] !~ '[2-9]'
        return ''
    else
        return ret
    endif
endfunction

Tags:

construct:assignment
construct:boolean
construct:elseif
construct:endif
construct:function
construct:if
construct:indexing
construct:invocation
construct:logical-and
construct:logical-or
construct:number
construct:parameter
construct:return
construct:string
construct:substring
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:functional
paradigm:reflective
technique:boolean-logic
technique:regular-expression
uses:substrings
uses:vim
ErikSchierboom commented 10 months ago

Exercise: phone-number

Code

function! ToNANP(number) abort
  let l:number = substitute(a:number, '\v[^0-9]', '', 'g')
  if match(l:number, '\v^1?[2-9][0-9]{2}[2-9][0-9]{6}$')
    let l:number = ''
  endif
  return strlen(l:number) ==# 11 ? l:number[1:] : l:number
endfunction

Tags:

construct:assignment
construct:conditional
construct:function
construct:function-definition
construct:if
construct:implicit-number-conversion
construct:index
construct:invocation
construct:let
construct:number
construct:parameter
construct:return
construct:string
construct:ternary
construct:variable-shadowing
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:metaprogramming
paradigm:object-oriented
technique:regular-expression
uses:Vim
ErikSchierboom commented 10 months ago

Exercise: nucleotide-count

Code

"
" Given a DNA string, compute how many times each nucleotide occurs in the
" string.
"
" Examples:
"
"   :echo NucleotideCount('ACGTACGT')
"   {'A': 2, 'C': 2, 'T': 2, 'G': 2}
"
"   :echo NucleotideCount('ACGTXACGT')
"   E605: Exception not caught: invalid nucleotide in strand
"

function! NucleotideCount(strand) abort
    if a:strand =~ '[^ACGT]'
        throw 'invalid nucleotide in strand'
    endif
    let l:count = {'A': 0, 'C': 0, 'G': 0, 'T': 0}
    for i in range(strlen(a:strand))
        let l:count[a:strand[i]] += 1
    endfor
    return l:count
endfunction

Tags:

construct:assignment
construct:dictionary
construct:endif
construct:for-loop
construct:function
construct:if
construct:indexing
construct:invocation
construct:let
construct:loop
construct:number
construct:parameter
construct:return
construct:string
construct:throw
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:functional
paradigm:object-oriented
technique:exceptions
technique:looping
uses:Dictionary
ErikSchierboom commented 10 months ago

Exercise: allergies

Code

let s:allergies = {
    \ 1: 'eggs', 2: 'peanuts', 4: 'shellfish',
    \ 8: 'strawberries', 16: 'tomatoes',
    \ 32: 'chocolate', 64: 'pollen', 128: 'cats' }

let s:log2 = { n -> log10(n) / log10(2) }

let s:next_power_of_2 =
    \ { n -> float2nr(pow(2, floor(s:log2(n)))) }

func! s:powers_of_2 (n) abort
    let pows = []
    let step = a:n
    while step > 0
        let next = s:next_power_of_2(step)
        call add(pows, next)
        let step -= next
    endwhile
    return pows
endfunc

func! AllergicTo(score, allergy) abort
    for p in s:powers_of_2(a:score)
        let found = get(s:allergies, p, v:null)
        if found == a:allergy
            return 1
        endif
    endfor
    return 0
endfunc

func! List(score) abort
    let all = []
    for p in s:powers_of_2(a:score)
        if has_key(s:allergies, p)
            call add(all, get(s:allergies, p))
        endif
    endfor
    return reverse(all)
endfunc

Tags:

construct:assignment
construct:call
construct:dictionary
construct:divide
construct:float
construct:floating-point-number
construct:for-loop
construct:if
construct:implicit-conversion
construct:index
construct:invocation
construct:lambda
construct:list
construct:number
construct:parameter
construct:return
construct:string
construct:subtract
construct:variable
construct:while-loop
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:looping
ErikSchierboom commented 10 months ago

Exercise: scrabble-score

Code

"
" Given a word, return the scrabble score for that word.
"
"    Letter                           Value
"    A, E, I, O, U, L, N, R, S, T     1
"    D, G                             2
"    B, C, M, P                       3
"    F, H, V, W, Y                    4
"    K                                5
"    J, X                             8
"    Q, Z                             10

let s:LettersGroups = {
  \ "aeioulnrst": 1,
  \ "dg": 2,
  \ "bcmp": 3,
  \ "fhvwy": 4,
  \ "k": 5,
  \ "jx": 8,
  \ "qz": 10,
  \ }

function! s:Value(char) abort
  let reg = a:char
  for letters in keys(s:LettersGroups)
    if letters =~ reg
      return s:LettersGroups[letters]
    endif
  endfor
endfunction

function! Score(word) abort
  let count = 0
  let chars = split(tolower(a:word), '\zs')
  for char in chars
    let val = s:Value(char)
    let count += val
  endfor

  return count
endfunction

Tags:

construct:assignment
construct:char
construct:dictionary
construct:for-loop
construct:function
construct:if
construct:indexing
construct:invocation
construct:let
construct:method
construct:number
construct:parameter
construct:return
construct:string
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:functional
paradigm:object-oriented
technique:looping
uses:Dictionary
ErikSchierboom commented 10 months ago

Exercise: scrabble-score

Code

let s:scoreletters = {
\       1: 'AEILNORSTU',
\       2: 'DG',
\       3: 'BCMP',
\       4: 'FHVWY',
\       5: 'K',
\       8: 'JX',
\       10: 'QZ',
\   }

let s:letterscores = map(range(26), 0)
for s:score in keys(s:scoreletters)
  for s:letter in split(s:scoreletters[s:score], '\zs')
    let s:letterscores[char2nr(s:letter) - s:a_char] = s:score
  endfor
endfor

function! Score(word) abort
    let l:a_char = char2nr('A')
    let l:total = 0
    for l:item in split(a:word->toupper(), '\zs')
      let l:total = l:total + s:letterscores[char2nr(l:item) - l:a_char]
    endfor

    return l:total

endfunction

Tags:

construct:add
construct:assignment
construct:char
construct:dictionary
construct:for-loop
construct:function
construct:implicit-conversion
construct:indexing
construct:invocation
construct:lambda
construct:let
construct:map
construct:number
construct:parameter
construct:return
construct:string
construct:subtract
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:looping
ErikSchierboom commented 10 months ago

Exercise: triangle

Code

function! Equilateral(triangle) abort
    return CheckInequality(a:triangle) && len(uniq(sort(a:triangle))) == 1
endfunction

function! Isosceles(triangle) abort
    return CheckInequality(a:triangle) && len(uniq(sort(a:triangle))) <= 2
endfunction

function! Scalene(triangle) abort
    return CheckInequality(a:triangle) && a:triangle[0] != a:triangle[1]
endfunction

function! CheckInequality(triangle) abort
    return count(a:triangle, 0) == 0
      \ && a:triangle[0] + a:triangle[1] >= a:triangle[2]
      \ && a:triangle[0] + a:triangle[2] >= a:triangle[1]
      \ && a:triangle[1] + a:triangle[2] >= a:triangle[0]
endfunction

Tags:

construct:add
construct:boolean
construct:function
construct:functional
construct:invocation
construct:logical-and
construct:number
construct:parameter
construct:return
construct:string
construct:variable
paradigm:functional
paradigm:imperative
paradigm:reflective
technique:boolean-logic
ErikSchierboom commented 10 months ago

Exercise: etl

Code

func! Transform(scores) abort
    let new_map = {}
    for pt in keys(a:scores)
        for ch in a:scores[pt]
            let new_map[tolower(ch)] = str2nr(pt)
        endfor
    endfor
    return new_map
endfunc

Tags:

construct:assignment
construct:dictionary
construct:endfor
construct:for
construct:function
construct:function-definitions
construct:implicit-conversion
construct:indexing
construct:invocation
construct:let
construct:loop
construct:lowercase
construct:parameter
construct:return
construct:string
construct:throw
construct:variable
construct:visibility-modifiers
paradigm:imperative
paradigm:functional
paradigm:reflective
technique:exceptions
technique:looping
ErikSchierboom commented 10 months ago

Exercise: pangram

Code

"
" Determine if a sentence is a pangram.
"
" A pangram is a sentence using every letter of the alphabet at least once.
"
" The alphabet used consists of ASCII letters a to z, inclusive, and is case
" insensitive. Input will not contain non-ASCII symbols.
"
" Example:
"
"     :echo IsPangram('The quick brown fox jumps over the lazy dog')
"     1
"     :echo IsPangram('The quick brown fox jumps over the lazy do')
"     0
"
function! IsPangram(sentence) abort
    const l:false = 0
    const l:true = 1
    let l:set = {}
    for l:character in a:sentence->tolower()
        let l:set[l:character] = v:null
    endfor
    for l:character in 'abcdefghijklmnopqrstuvwxyz'
        if !l:set->has_key(l:character)
            return l:false
        endif
    endfor
    return l:true
endfunction

Tags:

construct:boolean
construct:const
construct:for-loop
construct:function
construct:if
construct:indexing
construct:invocation
construct:let
construct:looping
construct:number
construct:parameter
construct:return
construct:string
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:looping
paradigm:object-oriented
technique:looping
ErikSchierboom commented 10 months ago

Exercise: pangram

Code

"
" Determine if a sentence is a pangram.
"
" A pangram is a sentence using every letter of the alphabet at least once.
"
" The alphabet used consists of ASCII letters a to z, inclusive, and is case
" insensitive. Input will not contain non-ASCII symbols.
"
" Example:
"
"     :echo IsPangram('The quick brown fox jumps over the lazy dog')
"     1
"     :echo IsPangram('The quick brown fox jumps over the lazy do')
"     0
"

function! IsPangram(sentence) abort
   let map = {}
   for letter in tolower(a:sentence)
      if (letter <= 'z' && letter >= 'a')
         let map[letter] = get(map,letter,0)+1
      endif
   endfor
   return len(map) == 26
endfunction

Tags:

construct:add
construct:assignment
construct:boolean
construct:dictionary
construct:endif
construct:for-loop
construct:function
construct:if
construct:implicit-conversion
construct:indexing
construct:invocation
construct:let
construct:number
construct:parameter
construct:return
construct:string
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:looping
uses:Dictionary
ErikSchierboom commented 10 months ago

This is an automated comment

Hello :wave: Next week we're going to start using the tagging work people are doing on these. If you've already completed the work, thank you! If you've not, but intend to this week, that's great! If you're not going to get round to doing it, and you've not yet posted a comment letting us know, could you please do so, so that we can find other people to do it. Thanks!