这里是使用 Racket 完成 HackerRank 函数式编程题目的第一章,包含基础函数和列表操作(0 - 10 题)。
仓库:13m0n4de/HackerRank-FP-Solutions
00-Solve Me First FP
使用 read 读取命令行输入的两个数字,相加之后使用 display 输出结果。
#lang racket (display (+ (read) (read)))
read 读取表达式并返回对应的值。
(read [in]) → any in : input-port? = (current-input-port)
01-Hello World
#lang racket (display "Hello World")
02-Hello World N Times
使用 in-range 创建一个长度为输入数值的序列,并在每次迭代它时输出 Hello World\n。
#lang racket (for ([_ (in-range (read))]) (display "Hello World\n"))
03-List Replication
函数签名:
replicate-elements : Integer (Listof Integer) -> (Listof Integer)
利用 append-map 和 make-list 创建元素重复的新列表。
#lang racket ;; replicate-elements : Integer (Listof Integer) -> (Listof Integer) (define (replicate-elements n lst) (append-map (lambda (num) (make-list n num)) lst)) (define (read-list) (let read-list-helper ([acc '()]) (let ([x (read)]) (if (eof-object? x) (reverse acc) (read-list-helper (cons x acc)))))) (let* ([input (read-list)] [n (car input)] [lst (cdr input)]) (for-each displayln (replicate-elements n lst)))
(HackerRank 居然不支持 typed/racket)
04-Filter Array
函数签名:
filter-less-than : Integer (Listof Integer) -> (Listof Integer)
使用 filter 过滤出小于 delim 元素。
#lang racket ;; filter-less-than : Integer (Listof Integer) -> (Listof Integer) (define (filter-less-than delim lst) (filter (lambda (num) (< num delim)) lst)) (define (read-list) (let read-list-helper ([acc '()]) (let ([x (read)]) (if (eof-object? x) (reverse acc) (read-list-helper (cons x acc)))))) (let* ([input (read-list)] [n (car input)] [lst (cdr input)]) (for-each displayln (filter-less-than n lst)))
05-Filter Positions in a List
函数签名:
remove-odd : (Listof Integer) -> (Listof Integer)
remove-odd-helper 函数检测当前元素位置 index 是否为奇数:
- 如果是奇数,则不修改累加器
acc,直接递归调用remove-odd-helper; - 如果是偶数,则将当前元素加入累加器
acc,而后递归调用remove-odd-helper。
列表处理完毕时,返回累加器 acc 的倒序。
#lang racket ;; remove-odd : (Listof Integer) -> (Listof Integer) (define (remove-odd lst) (let remove-odd-helper ([lst lst] [index 0] [acc '()]) (cond [(empty? lst) (reverse acc)] [(odd? index) (remove-odd-helper (cdr lst) (+ index 1) acc)] [else (remove-odd-helper (cdr lst) (+ index 1) (cons (car lst) acc))]))) (define (read-list) (let read-list-helper ([acc '()]) (let ([x (read)]) (if (eof-object? x) (reverse acc) (read-list-helper (cons x acc)))))) (let* ([input (read-list)] [lst (cdr input)]) (for-each displayln (remove-odd lst)))
06-Array Of N Elements
identity 函数不做任何操作,只是将其参数原样返回,所以 (build-list n identity) 可以得到从 0 到 n - 1 的列表。
#lang racket (define (f n) (build-list n identity)) (define n (string->number (read-line (current-input-port) 'any))) (print (list(f n)))
我不喜欢它给我的代码模板。
07-Reverse a List
要求不能使用 reverse 函数。
函数签名:
reverse-list : (Listof Integer) -> (Listof Integer)
递归地从列表头部开始,每次将列表的第一个元素添加到累积结果的前面,直到列表为空,这样就实现了列表的翻转。
#lang racket ;; reverse-list : (Listof Integer) -> (Listof Integer) (define (reverse-list lst) (let reverse-list-helper ([lst lst] [acc '()]) (cond [(empty? lst) acc] [else (reverse-list-helper (cdr lst) (cons (car lst) acc))]))) (define (read-list) (let read-list-helper ([acc '()]) (let ([x (read)]) (if (eof-object? x) (reverse acc) (read-list-helper (cons x acc)))))) (for-each displayln (reverse-list (read-list)))
相当于使用 foldl + cons:
(define (reverse-list lst) (foldl cons '() lst))
08-Sum of Odd Elements
函数签名:
sum-odd : (Listof Integer) -> Integer
手动递归版:
#lang racket ;; sum-odd : (Listof Integer) -> Integer (define (sum-odd lst) (let sum-odd-helper ([lst lst] [acc 0]) (cond [(empty? lst) acc] [else (define x (car lst)) (if (odd? x) (sum-odd-helper (cdr lst) (+ acc x)) (sum-odd-helper (cdr lst) acc))]))) (define (read-list) (let read-list-helper ([acc '()]) (let ([x (read)]) (if (eof-object? x) (reverse acc) (read-list-helper (cons x acc)))))) (displayln (sum-odd (read-list)))
使用 apply + filter:
(define (sum-odd lst) (apply + (filter odd? lst)))
09-List Length
函数签名:
list-length (Listof Integer) -> Integer
#lang racket ;; list-length (Listof Integer) -> Integer (define (list-length lst) (let list-length-helper ([lst lst] [acc 0]) (if (empty? lst) acc (list-length-helper (cdr lst) (+ acc 1))))) (define (read-list) (let read-list-helper ([acc '()]) (let ([x (read)]) (if (eof-object? x) (reverse acc) (read-list-helper (cons x acc)))))) (displayln (list-length (read-list)))
10-Update List
函数签名:
update-list : (Listof Integer) -> (Listof Integer)
map + abs。
#lang racket ;; update-list : (Listof Integer) -> (Listof Integer) (define (update-list lst) (map abs lst)) (define (read-list) (let read-list-helper ([acc '()]) (let ([x (read)]) (if (eof-object? x) (reverse acc) (read-list-helper (cons x acc)))))) (for-each displayln (update-list (read-list)))