## Problem: Add ### Statement Write a function that returns the sum of two numbers. ### Solutions #### Option 1 ```rust fn add(param1: Int, param2: Int){ param1 + param2 } ``` #### Option 2 ```rust fn add(a: Int, b: Int) -> Int {a + b} ``` ## Problem: Make Array Consecutive 2 ### Statement Ratiorg got `statues` of _different_ sizes as a present from CodeMaster for his birthday, each statue having an non-negative integer size. Since he likes to make things perfect, he wants to arrange them from smallest to largest so that each statue will be bigger than the previous one exactly by `1`. He may need some additional statues to be able to accomplish that. Help him figure out the minimum number of additional statues needed. **Example**: For `statues = [6, 2, 3, 8]`, the output should be `make_array_consecutive_2(statues) = 3`. Ratiorg needs statues of sizes `4`, `5` and `7`. ### Solutions #### Option 1 ```rust use aiken/list use aiken/int use aiken/math fn make_array_consecutive_2(xs: List<Int>) -> Int { let vmax = list.foldl(xs, 0, fn(n, reduced) { math.max(n, reduced) }) let vmin = list.foldl(xs, 1000, fn(n, reduced) { math.min(n, reduced) }) vmax - vmin + 1 - list.length(xs) } ``` #### Option 2 ```rust use aiken/list use aiken/int use aiken/option fn make_array_consecutive_2(xs: List<Int>) -> Int { let sorted = list.sort(xs, int.compare) option.or_else(list.last(sorted), 0) - option.or_else(list.head(sorted), 0) + 1 - list.length(xs) } ``` ## Problem: Circle of Numbers ### Statement Consider integer numbers from `0` to `n - 1` written down along the circle in such a way that the distance between any two neighboring numbers is equal (note that `0` and `n - 1` are neighboring, too). Given `n` and `firstNumber`, find the number which is written in the radially opposite position to `firstNumber`. **Example**: For `n = 10` and `firstNumber = 2`, the output should be `circle_of_numbers(n, firstNumber) = 7`. ### Solutions #### Option 1 ```rust fn circle_of_numbers(n: Int, firstNumber: Int) -> Int { (firstNumber + n / 2) % n } ``` #### Option 2 ```rust fn circle_of_numbers(n: Int, firstNumber: Int) -> Int { let res = firstNumber + n / 2 if (res >= n) { res - n } else { res } } ``` ## Problem: evenDigitsOnly ### Statement Check if all digits of the given integer are even. ### Solutions #### Option 1 ```rust fn evenDigitsOnly(n: Int) -> Bool { if (n == 0) { True } else if (n % 2 != 0) { False } else { evenDigitsOnly(n / 10) } } ``` ## Problem: chessBoardCellColor ### Statement Given two cells on the standard chess board, determine whether they have the same color or not. ### Solutions #### Option 1 ```rust use aiken/bytearray fn chessBoardCellColor(c1: ByteArray, c2: ByteArray) -> Bool { let x1 = bytearray.foldl(c1, 0, fn(byte, acc) { byte + acc}) let x2 = bytearray.foldl(c2, 0, fn(byte, acc) { byte + acc}) x1 % 2 == x2 % 2 } ``` #### Option 2 ```rust fn chessBoardCellColor(c1: ByteArray, c2: ByteArray) -> Bool { let x1 = bytearray.reduce(c1, 0, fn(byte, acc) { byte + acc}) let x2 = bytearray.reduce(c2, 0, fn(byte, acc) { byte + acc}) x1 % 2 == x2 % 2 } ``` ## Problem: [Aiken] Prove NFT Existence ### Statement Write a function to proves that within a given value, there exists a Policy ID with a single token name having a quantity of 1. ### Solutions #### Option 1 ```rust use aiken/dict use aiken/list use aiken/transaction/value.{PolicyId, Value} pub fn has_nfts(pid: PolicyId, total: Value) { when value.tokens(total, pid) |> dict.to_list is { [(_name, qty)] -> qty == 1 _ -> False } } ``` #### Option 2 ```rust fn has_nfts(pid: PolicyId, total: Value) { let tkns: List<Int> = value.tokens(total, pid) |> dict.values() let sum: Int = list.foldl(tkns, 0, fn(n, total) { n + total }) and { // must have only one asset name list.length(tkns) == 1, sum == 1, } } ``` ## Problem: [Aiken] Split list ### Statement Write a function to divide the list into two parts: the first part contains the first n elements of the original list, and the second part contains the remaining elements. If n is negative or greater than the length of the list, the first part will be empty, and the second part will contain the entire original list. ``` Example: span([1, 2, 3, 4, 5], 3) == ([1, 2, 3], [4, 5]) ``` ### Solutions #### Option 1 ```rust use aiken/list pub fn span(self: List<a>, n: Int) -> (List<a>, List<a>) { if n < 0 || n > list.length(self) { ([], self) } else { list.span(self, n) } ``` #### Option 2 ```rust use aiken/list fn span(self: List<a>, n: Int) -> (List<a>, List<a>) { if n < 0 || n > list.length(self) { ([], self) } else { (list.slice(self, 0, n - 1), list.slice(self, n, list.length(self) - 1)) } } ``` #### Option 3 ```rust fn span(self: List<a>, n: Int) -> (List<a>, List<a>) { when self is { [] -> ([], []) [x, ..xs] -> if n <= 0 { ([], self) } else { let (left, right) = span(xs, n - 1) ([x, ..left], right) } } } ``` ## Problem: [Aiken] Identify Spent Input ### Statement Check if a specific input by output reference is being spent. This is useful when a minting script requires a utxo to be spent but doesn't need any specific information about that input. ### Solutions #### Option 1 ```rust use aiken/transaction.{ InlineDatum, Input, Output, OutputReference, TransactionId, } use aiken/list // dont remove imports pub fn is_spending_input(inputs: List<Input>, out_ref: OutputReference) -> Bool { list.any(inputs, fn(in) { in.output_reference == out_ref }) } ``` #### Option 2 ```rust use aiken/transaction.{ InlineDatum, Input, Output, OutputReference, TransactionId, } pub fn is_spending_input(inputs: List<Input>, out_ref: OutputReference) -> Bool { when transaction.find_input(inputs, out_ref) is { None -> False _ -> True } } ``` ### Option 3 ```rust use aiken/transaction.{ InlineDatum, Input, Output, OutputReference, TransactionId, } pub fn is_spending_input(inputs: List<Input>, out_ref: OutputReference) -> Bool { // write your code here when inputs is { [input, ..rest] -> if input.output_reference == out_ref { // it is being spent True } else { is_spending_input(rest, out_ref) } // nothing is found so fail [] -> fail @"Input Not Spent" } } ``` ## Problem: [Aiken] Create an output reference ### Statement Create an `OutputReference` from the `TxId#Idx` information. This is useful for building correct output references of specific UTxOs. ### Solutions #### Option 1 ```rust use aiken/transaction.{ OutputReference,TransactionId, } pub fn out_ref(tx_id_hash: ByteArray, idx: Int) -> OutputReference { // write your code here OutputReference(TransactionId(tx_id_hash), idx) } ``` #### Option 2 ```rust use aiken/transaction.{ OutputReference,TransactionId, } pub fn out_ref(tx_hash: ByteArray, idx: Int) -> OutputReference { // write your code here OutputReference(TransactionId(tx_hash), idx) } ``` ## Problem: [Aiken] Retrieve Datum Data by Hash ### Statement Find the datum data on a input by the datum hash or error. The data is assumed to be embedded data and must be referenced by its hash ### Solutions #### Option 1 ```rust use aiken/dict.{Dict} use aiken/hash.{Blake2b_224, Blake2b_256, Hash} use aiken/transaction.{DatumHash, NoDatum, InlineDatum, Input, Output, OutputReference, TransactionId} pub fn input_datum_by_hash( possible_input: Input, datums: Dict<Hash<Blake2b_256, Data>, Data>, ) -> Data { // Write your code here expect Some(resolved_datum) = when possible_input.output.datum is { NoDatum -> None DatumHash(h) -> dict.get(datums, h) InlineDatum(d) -> Some(d) } resolved_datum } ``` #### Option 2 ```rust use aiken/dict.{Dict} use aiken/hash.{Blake2b_224, Blake2b_256, Hash} use aiken/transaction.{DatumHash, Input, Output, OutputReference, TransactionId} pub fn input_datum_by_hash( possible_input: Input, datums: Dict<Hash<Blake2b_256, Data>, Data>, ) -> Data { // Write your code here when possible_input.output.datum is { DatumHash(inbound_datum_hash) -> when dict.get(datums, inbound_datum_hash) is { Some(inbound_datum) -> inbound_datum _ -> fail @"No Input Datum Attached" } _ -> fail @"No Input Datum" } } ``` ## Problem: [Aiken] Verify Script Output Count ### Statement Verify that the number of outputs from a specific script is equal the amount intended in the contract. The amount must be exact with the counter. ### Solutions #### Option 1 ```rust use aiken/transaction.{Input, Output,OutputReference, Transaction, Spend, InlineDatum, TransactionId, NoDatum} use aiken/transaction/credential.{Address,Script, VerificationKey,Referenced, Credential, StakeCredential, Inline, ScriptCredential} use aiken/list pub fn outputs_by_addr( outputs: List<Output>, addr: Address, amount: Int, ) -> Bool { // write your code here amount == list.count(outputs, fn(out) { out.address.payment_credential == addr.payment_credential}) } ``` #### Option 2 ```rust use aiken/transaction.{Input, Output,OutputReference, Transaction, Spend, InlineDatum, TransactionId, NoDatum} use aiken/transaction/credential.{Address,Script, VerificationKey,Referenced, Credential, StakeCredential, Inline, ScriptCredential} pub fn outputs_by_addr( outputs: List<Output>, addr: Address, amount: Int, ) -> Bool { // write your code here do_outputs_by_addr(outputs, addr, 0) == amount } // Internal only fn do_outputs_by_addr(outputs: List<Output>, addr: Address, counter: Int) -> Int { when outputs is { [output, ..rest] -> // exact address match if output.address == addr { do_outputs_by_addr(rest, addr, counter + 1) } else { do_outputs_by_addr(rest, addr, counter) } // loop entire list then return counter [] -> counter } } ```