Closed iHiD closed 11 months ago
let hello = () => "Hello, World!";
construct:arrow-function
construct:expression
construct:function
construct:implicit-conversion
construct:let-binding
construct:string
construct:underscore-string
construct:value
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
type planet =
| Mercury
| Venus
| Earth
| Mars
| Jupiter
| Saturn
| Uranus
| Neptune;
let secondsToEarthYears = seconds => seconds /. 31557600.0;
// Get the orbital period in Earth years
let orbitalPeriod = planet => {
switch (planet) {
| Mercury => 0.2408467
| Venus => 0.61519726
| Earth => 1.0
| Mars => 1.8808158
| Jupiter => 11.862615
| Saturn => 29.447498
| Uranus => 84.016846
| Neptune => 164.79132
};
};
// Return someone's age on a given planet.
let ageOn = (planet, ageInSeconds) =>
secondsToEarthYears(ageInSeconds) /. orbitalPeriod(planet);
construct:comment
construct:divide
construct:float
construct:floating-point-number
construct:function
construct:invocation
construct:lambda
construct:let-binding
construct:number
construct:parameter
construct:pipe-forward
construct:switch
construct:tuple
construct:type-constructor
construct:variant
construct:vertical-bar
paradigm:functional
paradigm:object-oriented
technique:higher-order-functions
uses:planet
let hey = phrase => {
let p = Js.String.trim(phrase);
let phraseIs = regx => Js.Re.fromString(regx) |> Js.Re.test(p);
let yelling = "^(?=.*[A-Z])[^a-z]*$";
let yelled_question = "^[^a-z0-9]*\?$";
let question = ".*\?$";
switch (p) {
| "" => "Fine. Be that way!"
| _ when phraseIs(yelled_question) => "Calm down, I know what I'm doing!"
| _ when phraseIs(question) => "Sure."
| _ when phraseIs(yelling) => "Whoa, chill out!"
| _ => "Whatever."
};
};
construct:application
construct:functor
construct:invocation
construct:lambda
construct:let
construct:method
construct:parameter
construct:pattern-matching
construct:pipe-forward
construct:string
construct:switch
construct:underscore
construct:variable
paradigm:functional
paradigm:object-oriented
technique:higher-order-functions
technique:regular-expression
uses:Js.Re
uses:Js.String
let wordBreak = [%bs.re {|/[\W]{2,}|[^0-9a-z']/|}];
let optionOr = (key, x) =>
switch (key) {
| Some(y) => y
| None => x
};
let getDefault = (dict, key, default) =>
optionOr(Js.Dict.get(dict, key), default);
let wordCount = text =>
text
|> String.lowercase
|> Js.String.splitByRe(wordBreak)
|> Js.Array.filter(word => word != "")
|> Array.fold_left(
(dict, word) => {
Js.Dict.set(dict, word, getDefault(dict, word, 0) + 1);
dict;
},
Js.Dict.empty(),
)
|> Js.Dict.entries;
construct:array
construct:binding
construct:char
construct:curried-application
construct:dictionary
construct:expression
construct:function
construct:implicit-conversion
construct:int
construct:integral-number
construct:invocation
construct:lambda
construct:let
construct:method
construct:number
construct:parameter
construct:pattern-matching
construct:string
construct:switch
construct:tuple
construct:underscore-number
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
uses:Js.Array
uses:Js.Dict
let wordCount = phrase =>
Js.String.(
phrase
|> toLowerCase
|> replaceByRe([%re "/[^'a-z0-9]+/g"], " ")
|> trim
|> splitByRe([%re "/'?\\s+'?/"])
|> Js.Array.reduce(
(dict, word) => {
(
switch (Js.Dict.get(dict, word)) {
| Some(count) => count + 1
| None => 1
}
)
|> Js.Dict.set(dict, word);
dict;
},
Js.Dict.empty(),
)
|> Js.Dict.entries
);
construct:add
construct:binding
construct:char
construct:curried-function
construct:dictionary
construct:expression
construct:fat-arrow
construct:function
construct:implicit-conversion
construct:invocation
construct:lambda
construct:let
construct:method
construct:number
construct:parameter
construct:pattern-matching
construct:string
construct:switch
construct:tuple
construct:underscore
construct:variable
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
uses:Js.Dict
let wordCount = (sentence: string): array((string, int)) => {
let words = Js.String.splitByRe([%bs.re {|/\s/g|}], sentence)
|> Js.Array.map((word: string) => {
Js.String.replaceByRe([%bs.re {|/^'|[^a-zA-Z1-9']|'$/g|}], "", word)
|> Js.String.toLowerCase
})
|> Js.Array.filter((word) => Js.String.length(word) > 0)
|> Js.Array.reduce((accum: Js.Dict.t(int), word: string) => {
let currentCount = switch(Js.Dict.get(accum, word)) {
| Some(number) => number
| None => 0
};
Js.Dict.set(accum, word, currentCount + 1);
accum
}, Js.Dict.empty());
Js.Dict.keys(words)
|> Js.Array.map((word: string) => (word, Js.Dict.unsafeGet(words, word)))
}
construct:big-int
construct:binding
construct:boolean
construct:char
construct:curried-function
construct:dictionary
construct:expression
construct:functor
construct:implicit-conversion
construct:int
construct:integral-number
construct:invocation
construct:js-function
construct:let
construct:number
construct:parameter
construct:pattern-matching
construct:record
construct:string
construct:switch
construct:tuple
construct:underscore-char
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:object-oriented
technique:higher-order-functions
uses:Js.Dict
uses:Js.String
let validate = number => {
let splittedNumber = string_of_int(number) |> Js.String.split("");
let numberOfDigits = Array.length(splittedNumber);
let result =
splittedNumber
|> Js.Array.map(int_of_string)
|> Js.Array.reduce(
(acc, digit) => acc + Js.Math.pow_int(digit, numberOfDigits),
0,
);
result == number;
};
construct:add
construct:array
construct:curried-function
construct:equivalence
construct:implicit-conversion
construct:int
construct:integral-number
construct:invocation
construct:lambda
construct:let-binding
construct:number
construct:parameter
construct:pipe-forward
construct:string
construct:underscore
construct:variable
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
let strToSortedArray = (s: string) : array(string) =>
Js.Array.sortInPlace(Js.String.split("", String.lowercase(s)));
let anagrams = (word: string, possibleAnagrams: list(string)) : list(string) =>
if (word === String.uppercase(word)) {
[];
} else {
let wordArr: array(string) = strToSortedArray(word);
List.filter(
(w: string) => strToSortedArray(w) == wordArr,
possibleAnagrams,
);
};
construct:array
construct:assignment
construct:if
construct:implicit-conversion
construct:invocation
construct:lambda
construct:list
construct:let
construct:string
construct:tuple
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
uses:List
let alphabet = Array.make(26, 0) |> Array.mapi((i, _) => Char.chr(i + 65));
let maxL = Array.length(alphabet) - 1;
let rec checkContains = (string, index) => {
let charT = alphabet[index];
let x = String.contains(string, charT);
switch (index < maxL && x) {
| true => checkContains(string, index + 1)
| _ => x
};
};
let isPangram = input => input |> String.uppercase |> checkContains(_, 0);
construct:add
construct:boolean
construct:char
construct:curried-function
construct:function
construct:implicit-conversion
construct:indexing
construct:int
construct:integral-number
construct:invocation
construct:lambda
construct:let-binding
construct:logical-and
construct:number
construct:parameter
construct:pattern-matching
construct:recursion
construct:string
construct:subtract
construct:switch
construct:underscore
construct:variable
paradigm:functional
paradigm:imperative
paradigm:logical
paradigm:object-oriented
technique:boolean-logic
technique:higher-order-functions
technique:looping
let rec binarySearch = (a: array(int), i: int, b: int, e: int): option(int) => {
let middleIndex = b + (e - b) / 2;
let middle = a[middleIndex];
if (middle == i) {
Some(middleIndex);
} else if (b == e) {
None;
} else if (middle > i) {
binarySearch(a, i, b, middleIndex);
} else {
binarySearch(a, i, min(middleIndex + 1, e), e);
};
};
let find = (a: array(int), i: int) => Array.length(a) > 0 ? binarySearch(a, i, 0, Array.length(a) - 1) : None;
construct:add
construct:array
construct:boolean
construct:divide
construct:if
construct:implicit-conversion
construct:index-access
construct:int
construct:integral-number
construct:invocation
construct:lambda
construct:let
construct:method
construct:number
construct:parameter
construct:pattern-matching
construct:recursion
construct:subtract
construct:ternary
construct:tuple
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:bit-manipulation
technique:bit-shifting
technique:higher-order-functions
technique:looping
technique:recursion
open Belt;
let explode = s => {
List.makeBy(String.length(s), String.get(s));
};
let implode = cs => {
String.concat("", List.map(cs, String.make(1)));
};
let rec span = (xs, p) => {
switch (xs) {
| [] => ([], [])
| [x, ...xs] when p(x) =>
let (us, vs) = span(xs, p);
([x, ...us], vs);
| xs => ([], xs)
};
};
let isDigit = c => {
let x = Char.code(c);
x >= Char.code('0') && x <= Char.code('9');
};
let encode = s => {
let rec aux =
fun
| [] => ""
| [c, ...cs] => {
let (us, vs) = span(cs, (==)(c));
let n = 1 + List.length(us);
let num =
if (n > 1) {
string_of_int(n);
} else {
"";
};
num ++ String.make(1, c) ++ aux(vs);
};
s |> explode |> aux;
};
let decode = s => {
let rec aux = digits =>
fun
| [] => ""
| [c, ...cs] when isDigit(c) => aux([c, ...digits], cs)
| [c, ...cs] => {
let n =
switch (digits) {
| [] => 1
| digits => digits |> List.reverse |> implode |> int_of_string
};
String.make(n, c) ++ aux([], cs);
};
s |> explode |> aux([]);
};
construct:add
construct:boolean
construct:char
construct:curried-function
construct:functor
construct:if-else
construct:implicit-conversion
construct:int
construct:integral-number
construct:invocation
construct:lambda
construct:let-binding
construct:list
construct:logical-and
construct:parameter
construct:pattern-matching
construct:recursion
construct:string
construct:switch
construct:underscore-char
construct:variable
construct:when-clause
construct:||
paradigm:functional
paradigm:object-oriented
technique:boolean-logic
technique:higher-order-functions
technique:looping
technique:recursion
uses:List
let mineCount = (grid, ~row, ~col) =>
try(
if (grid[row][col] == "*") {
1;
} else {
0;
}
) {
| _ => 0
};
let minesCount = (grid, ~row, ~col) => {
mineCount(grid, ~row=row - 1, ~col=col - 1)
+ mineCount(grid, ~row=row - 1, ~col)
+ mineCount(grid, ~row=row - 1, ~col=col + 1)
+ mineCount(grid, ~row, ~col=col - 1)
+ mineCount(grid, ~row, ~col)
+ mineCount(grid, ~row, ~col=col + 1)
+ mineCount(grid, ~row=row + 1, ~col=col - 1)
+ mineCount(grid, ~row=row + 1, ~col)
+ mineCount(grid, ~row=row + 1, ~col=col + 1);
};
let annotate: array(string) => array(string) =
grid => {
let grid = grid |> Array.map(Js.String.split(""));
grid
|> Js.Array.forEachi((row, rowIdx) => {
row
|> Js.Array.forEachi((_, colIdx) =>
if (grid[rowIdx][colIdx] != "*") {
let count = grid->minesCount(~row=rowIdx, ~col=colIdx);
if (count > 0) {
grid[rowIdx][colIdx] = count |> string_of_int;
};
}
)
});
grid |> Array.map(Js.Array.joinWith(""));
};
construct:add
construct:array
construct:boolean
construct:curried-function
construct:if-else
construct:implicit-conversion
construct:indexing
construct:int
construct:integral-number
construct:invocation
construct:lambda
construct:let-binding
construct:method
construct:number
construct:object
construct:optional-argument
construct:parameter
construct:pattern-matching
construct:pipe-forward
construct:string
construct:subtract
construct:try
construct:underscore-pattern
construct:variable-shadowing
construct:visibility-modifiers
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:exceptions
type coins = list(int);
let rec range = (start: int, end_: int): list(int) =>
if (start >= end_) {
[];
} else {
[start, ...range(start + 1, end_)];
};
let rec first = (f: 'a => option(list(int)), l: list('a)): option(list(int)) => {
switch(l) {
| [] => None
| [v, ...rest] => {
let r = f(v)
switch(r) {
| Some(b) => Some(b)
| None => first(f, rest)
}
}
}
}
let sum = (l: list(int)): int => (
List.fold_left(
(a, b) => a + b, 0, l
)
);
let rec combinations = (k: int, xxs: list(int)): list(list(int)) => {
switch(k, xxs) {
| (0, _) => [[]]
| (_, []) => []
| (k, [x, ...xs]) =>
List.append(
List.map(ys => [x, ...ys], combinations(k - 1, xxs)),
combinations(k, xs)
)
}
};
let generateForN = (availableCoins: list(int), target: int, n: int): option(list(int)) => {
if (n == 3) {
Js.log(combinations(n, availableCoins));
}
combinations(n, availableCoins)
|> first(
coins => {
if (sum(coins) == target) {
Some(coins)
} else {
None
}
}
)
};
let makeChange = (target: int, coins: coins) => {
if (target == 0) {
Some([]);
} else if (target < List.hd(coins)) {
None;
} else {
range(1, 20)
|> first(i => generateForN(coins, target, i))
}
};
construct:add
construct:application
construct:boolean
construct:curried-function
construct:if
construct:int
construct:integral-number
construct:invocation
construct:lambda
construct:let
construct:list
construct:number
construct:parameter
construct:pattern-matching
construct:recursion
construct:subtract
construct:switch
construct:tuple
construct:underscore-identifier
construct:variable
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:looping
uses:List
let change = (coins, input) => {
Array.sort((a, a') => {a == a' ? 0 : a > a' ? -1 : 1}, coins)
let resultArray = [||]
let rec ch = (coinIndex, valueleft) => {
if(valueleft != 0) {
if(coins[coinIndex] <= valueleft) {
let a = Js.Array.push(coins[coinIndex],resultArray);
ch(coinIndex, valueleft-coins[coinIndex]);
}
else if(coinIndex < Js.Array.length(coins)-1) {
ch(coinIndex+1, valueleft);
}
}
}
ch(0, input);
resultArray
};
construct:add
construct:boolean
construct:if
construct:if-expression
construct:implicit-conversion
construct:index-access
construct:int
construct:integral-number
construct:invocation
construct:lambda
construct:let
construct:method
construct:number
construct:parameter
construct:pattern-matching
construct:recursion
construct:subtract
construct:ternary
construct:tuple
construct:variable
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:looping
let split = Js.String.splitByRe([%re "/[ -]/"]);
let firstLetter = Js.String.slice(~from=0, ~to_=1);
let toUpperCase = Js.String.toUpperCase;
let abbreviate = (str: string) =>
Js.Array.reduce(
(acc, x) => acc ++ (x |> firstLetter |> toUpperCase),
"",
split(str),
);
construct:function
construct:implicit-conversion
construct:invocation
construct:lambda
construct:let-binding
construct:number
construct:parameter
construct:pattern
construct:pipeline
construct:string
construct:underscore
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:object-oriented
technique:function-composition
let intPow = (exponent, n) => (float_of_int(n) ** float_of_int(exponent)) |> int_of_float;
let rec toBase10 = (number, current_base, pos, value) => {
switch number {
| 0 => value
| _ => {
let v = (number mod 10) * intPow(pos, current_base);
toBase10(number/10, current_base, pos+1, v+value)
}
};
}
let rec toBase = (number, base, value) => {
switch number {
| 0 => value
| _ => {
let v = string_of_int(number mod base) ++ value
toBase(number/base, base, v)
}
}
}
construct:add
construct:divide
construct:float
construct:float-of-int
construct:floating-point-number
construct:function
construct:implicit-conversion
construct:int
construct:integral-number
construct:invocation
construct:lambda
construct:let-binding
construct:multiply
construct:number
construct:parameter
construct:pattern-matching
construct:recursion
construct:string
construct:switch
construct:underscore
construct:variable
construct:visibility-modifiers
paradigm:functional
paradigm:object-oriented
technique:higher-order-functions
technique:recursion
let decimal_to_digits = (base, decimal) => {
let rec base_conversion = (decimal, digits) =>
switch (decimal / base) {
| 0 => [decimal mod base, ...digits]
| quotient => base_conversion(quotient, [decimal mod base, ...digits])
};
base_conversion(decimal, []);
};
let digits_to_decimal = (base, digits) =>
digits
|> List.rev
|> List.mapi((i, x) => x * Js.Math.pow_int(~base, ~exp=i))
|> List.fold_left((+), 0);
let rebase = (from, digits, target) => {
let invalid_base = (from, target) => from <= 1 || target <= 1;
let invalid_digits = (from, digits) =>
List.filter(i => i >= from || i < 0, digits) !== []
or List.filter(i => i == 0, digits) == digits;
switch (from, digits, target) {
| (_, [], _) => None
| (from, _, target) when invalid_base(from, target) => None
| (from, digits, _) when invalid_digits(from, digits) => None
| (from, digits, target) =>
Some(digits_to_decimal(from, digits) |> decimal_to_digits(target))
};
};
construct:add
construct:boolean
construct:divide
construct:double
construct:equals
construct:floating-point-number
construct:functor
construct:implicit-conversion
construct:invocation
construct:lambda
construct:list
construct:logical-or
construct:multiply
construct:number
construct:optional-argument
construct:parameter
construct:pattern-matching
construct:pipelining
construct:recursion
construct:switch
construct:underscore
construct:variant
construct:visibility-modifiers
paradigm:functional
paradigm:object-oriented
technique:boolean-logic
technique:higher-order-functions
technique:looping
technique:recursion
uses:List
let rec accumulate = (f, elements) =>
switch elements {
| [] => []
| [head, ...tail] => [f(head), ...accumulate(f, tail)]
}
construct:array
construct:curried-function
construct:function
construct:invocation
construct:let
construct:list
construct:parameter
construct:pattern-matching
construct:recursion
construct:switch
construct:tuple
construct:variadic-function
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:recursion
let rec accumulate = (cb, list) =>
switch (list) {
| [] => []
| [head, ...tail] => [cb(head), ...accumulate(cb, tail)]
};
construct:array
construct:binding
construct:curried-function
construct:function
construct:invocation
construct:lambda
construct:list
construct:parameter
construct:pattern-matching
construct:recursion
construct:switch
construct:tuple
construct:variadic-function
paradigm:functional
paradigm:imperative
paradigm:object-oriented
technique:higher-order-functions
technique:recursion
open Jest;
describe("Resistor Color", () => {
open Expect;
open ResistorColor;
test("Black", () =>
expect(colorCode(Black)) |> toEqual(0)
);
test("White", () =>
expect(colorCode(White)) |> toEqual(9)
);
test("Orange", () =>
expect(colorCode(Orange)) |> toEqual(3)
);
// Since we have `color` datatype, colors list test from canonical data is skipped
})
comments
describe
empty-tail-calls
expect
function-calls
ignore
open
paradigm:functional
test
test-framework:Jest
uses:ResistorColor
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!
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:
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