DEV Community

Derk-Jan Karrenbeld
Derk-Jan Karrenbeld

Posted on • Edited on

Want to help people learn programming languages?

Exercism is an online platform designed to help you improve your coding skills through practice and mentorship. It currently provides over 50 language tracks.

Exercism provides you with thousands of exercises spread across numerous language tracks. Once you start a language track you are presented with a core set of exercises to complete. Each one is a fun and interesting challenge designed to teach you a little more about the features of a language.

At the moment of writing, I'm a maintainer of the JavaScript and TypeScript track and a while back we've started working on automating a part of the experience.

The post above talks extensively about how to write an analyzer and what went into this work.

As part of Hacktoberfest, I have updated the javascript-analyzer and javascript-track contributing guidelines. Other maintainers have done the same for their repositories.

What can you work on

Because there are so many projects running at Exercism, there is also a lot you can work on. Here is a short list of the things I find the most interesting.

I'm super biased, but with 160 repositories, and at least 90 active in the past month, there is plenty for anyone and everyone.

Help out your favourite language

Given that we have over 50 language tracks, your favourite language is possibly one of them. Many of them have open issues, and all of them allow for new exercises to be ported from other tracks.

Checklist: exercises that could be implemented #660

Hi there (new) contributors.

The way this works is you can follow the link below to the problem specifications. This is the canonical data we have for this exercise. If you want a grasp of how this exercise might look, have a look at other tracks, where this exercise is implemented. You'll probably want to start with similar languages such as typescript and coffeescript, and then perhaps other loosly-typed languages such as ruby or python.

  1. Open a new issue, we'll label it with new exercise ✨
  2. We'll assign the issue to you, so you get to work on this exercise
  3. Create a new folder in /exercises
  4. You'll need to sync this folder with the matching config files. You can use scripts/sync to do this: ASSIGNMENT=slug npx @babel/node scripts/sync.
  5. Create a <slug>.js stub file.
  6. Create a <slug>.spec.js test file. Here add the tests, per canonical data if possible.
  7. Create a example.js file. Place a working implementation, assuming it's renamed to <slug>.js
  8. Run the tests locally, using scripts/test: ASSIGNMENT=slug npx @babel/node scripts/test.
  9. Open a PR.

NOTE: Use this link for a ⚡️ live list of unimplemented exercises.

Write an analyzer, or help improving one

There are currently 17 (or more) analyzers! This means that there are many tracks without any analyzer infrastructure. If you know a language well, you can help out with that. However, I would love your help on the javascript-analyzer or typescript-analyzer.

  • Write a complete new analyzer for an existing exercise. We will provide 500 fixtures and what should be approved and what shouldn't. We'll help writing some initial messaging, you don't need to worry about that.
  • Help improving an existing analyzer. The coming week, more issues will be opened to indicate where improvement is required!

Improve resistor-color-duo: detect unary + #56

Describe the improvement:

When a solution has +expression instead of Number(expression), and it's otherwise optimal, we want to give a specific message. It should still approve, but add a message that Number(...) is preferred over unary +.

Which exercise

resistor-color-duo

Improve resistor-color-duo: detect string concat #55

Describe the improvement:

When the following main method is provided, the analyzer bails early:

export const value = arr => {
  return +(COLORS.indexOf(arr[0]) + "" + COLORS.indexOf(arr[1]));
};
Enter fullscreen mode Exit fullscreen mode

Instead, it should be caught by hasDigitsString, and produce the same comment.

Which exercise

resistor-color-duo

Additional context

The ResistorColorDuoSolution has a method that checks if an exercise has a constructed string. It currently only detects a string template literal that looks like ${a}${b}, but we want to also capture the following:

`${a}` + `${b}`
a + "" + b
a + '' + b
""  + a + b
''  + a + b
a.toString() + b
a.toString() + b.toString()
a.toString().concat(b)
Enter fullscreen mode Exit fullscreen mode

Add analyzer for rna-transcription #53

This issue is for discussion and assignment for the rna-transcription core exercise in the javascript track.

🔗 implementation | mentor-notes | problem-specification


This exercise focuses on

Optimal solution

const TRANSCRIPTION = {
  C: 'G',
  G: 'C',
  A: 'U',
  T: 'A',
};

export function toRna(sequence) {
  return sequence
    .split('')
    .map(nucleotide => TRANSCRIPTION[nucleotide])
    .join('')
}
Enter fullscreen mode Exit fullscreen mode

Variations include Set or Map with #get, which are valid!

Variations (approvable without comment)

String destructuring can also be used:

return [...sequence].map(/**/).join('')
Enter fullscreen mode Exit fullscreen mode

String#replace can also be used:

return sequence.replace(/./g, (nucleotide) => /* */)
Enter fullscreen mode Exit fullscreen mode

Variations include replacing only the "known" nucleotides:

sequence.replace(/[CGAT]g/, (nucleotide) => /* */)
Enter fullscreen mode Exit fullscreen mode

Helper function variation

Instead of an anonymous function, a helper function may be used:

function transcribe(nucleotide) {
  return TRANSCRIPTION[nucleotide]
}
Enter fullscreen mode Exit fullscreen mode

This also allows for a version without a mapping object:

function transcribe(nucleotide) {
  switch(nucleotide) {
    case 'C': { return 'G' }
    case 'G': { return 'C' }
    case 'A': { return 'U' }
    case 'T': { return 'A' }
  }
}
Enter fullscreen mode Exit fullscreen mode

SHOULD comment and disapprove

Cases we SHOULD comment on with this analyzer:

  • Use an Object to keep track of the mapping instead of conditionals.
  • Use iteration via String#split or String#replace instead of using for/forEach with Array#push
  • Discourage Array#reduce for this particular solution, because it creates a lot of intermediary strings (more than the split approach), except if the rest of the solution is correct (then you can mention it but approve). Using reduce requires more interpretation by the reader to follow, change and maintain.
  • Discourage String#substring with foreach iteration, because character iteration via split('') is more idiomatic and maintainable than substring with 1. Using split('') requires less interpretation by the reader to follow, change and maintain.

Approach

The suggested approach is to:

  • detect which type of solution it is (switch, map, or for/forEach)
  • make sure the optimal solution is correctly handled. You can use the batch runner to generate output for all fixtures.
  • go from there by adding paths to disapprove.

Join the mentors

Naturally, we are always looking for new mentors. You don't need to be an expert in your language, but we'd love it if you have extensive experience. You'll be coaching people on their journey to gain fluency. We also have a #mentor-the-mentor program, to help you get better at mentoring.

Join the students!

Know how to program in Java, but always wanted to learn Rust? Or maybe you finally make that step knowing TypeScript? Some tracks are currently oversubscribed, but in general we welcome anyone to become a student. Note: this is not a platform to teach you how to code. It's a platform to gain fluency in a new language.

Top comments (0)