newLisp Challenge 2!

Before we continue with Tutorial 5 on newLISP, let’s do now some exercises in newLISP programming. You’ve to solve some problems. To do so successfully, recall the contents of the first four tutorials on newLISP of mine. In addition, you can use this link for info on newLISP functions: http://www.newlisp.org/downloads/manual_frame.html

Notice that for some problems one could find better solutions when invoking other functions than discussed in the first four tutorials.

Below the solutions first for the beginner level tasks and then for the intermediate level.

A. Beginner level

1. Function Between
→ Returns the substring between e.g. { and }, if found, or returns nil.

Example:
Return 12 if the substring {12} exists in the input

Solution:
(if (find “{(.*)}” “There were {12} objects!” 1) $1)

Return value:
12

Source:
https://github.com/danielstjules/Stringy#betweenstring-start-string-end–int-offset

2. Function: Camelize
→ Returns a camelCase version of the string.

Requirements:
→ Trims surrounding spaces,
→ capitalizes letters following dashes and underscores and
→ removes dashes and underscores.

Examples:
Camel-Case -> camelCase
Camel_Case -> camelCase
Camel-case -> camelCase
CAMEL-cASE -> camelCase

Solution:
(append (first (parse (lower-case {CAMEL-cASE}) {_|-} 0 )) (title-case (apply string (rest (parse (lower-case {CAMEL-cASE}) {_|-} 0)))))

Notice that this function is less complex as it seems: at the end of this text, I’ll break it in the consisting parts. In addition, I’ll give a regex solution.

Return value:
camelCase

Source:
https://github.com/danielstjules/Stringy#camelize

3. Function Collapsewhitespace
→ Trims the string and replaces consecutive whitespace characters with a single space.

Solution:
(replace {[ ]+} (trim { A     B           C }) { } 0)

Return value:
A B C

Source:
https://github.com/danielstjules/Stringy#collapsewhitespace

4. Function Return-CSV
→ Returns a CSV-string consisting of the characters in the input, separated by e.g. delimiter ;

Solution:
(join (explode {ABC}) {;})

Return value:
A;B;C

Source (modified):
https://github.com/danielstjules/Stringy#chars

5. Function Countsubstring
→ Returns the number of occurrences of a substring in the given input.

Requirement:
→ Casesensitive.

Solution, casesensitive:
(if (find-all {a} {A little man shook his bald head.}) $count)

Return value:
3

Solution, caseinsensitive:
(if (find-all {A|a} {A little man shook his bald head.}) $count)

Return value:
4

Source:
https://github.com/danielstjules/Stringy#countsubstrstring-substring–boolean-casesensitive–true-

6. Function Dasherize
→ Returns a lowercase and trimmed string separated by dashes.

Requirements:
→ Dashes are inserted before uppercase characters (with the exception of the first character of the string).
→ Spaces as well as underscores are replaced by dashes.

Example:
fooBar -> foo-bar

Solution:
(trim (replace {([A-Z _]{1})} {FooBar} (append {-} (trim (trim (lower-case $1) “_”))) 0) “-“)

Return value:
foo-bar

Source:
https://github.com/danielstjules/Stringy#dasherize

7. Function EnsureLeft
→ Ensures that input begins with a specific prefix. If it doesn’t, it’s prepended.

Example (with prefix “https://”):
foobar.com -> https://foobar.com
https://foobar.com -> https://foobar.com

Solution:
(if (starts-with {foobar.com} {https://} 1) {foobar.com} (append {https://} {foobar.com} ))

Return value:
https://foobar.com

Source:
https://github.com/danielstjules/Stringy#ensureleftstring-substring

8. Function EnsureRight
→ Ensures that input ends with a specific suffix. If it doesn’t, it’s appended.

Example (here with suffix “.com”):
– foobar -> foobar.com
– foobar.com -> foobar.com

(if (ends-with {foobar} {.com} 1) {foobar} (append {foobar} {.com}))

Return value:
foobar.com

Source:
https://github.com/danielstjules/Stringy#ensurerightstring-substring

9. Function PadLeft
→ Returns a string of a given length (here 9) such that the beginning of the string is padded.

Solution:
(append (dup {$} (- 9 (length {abc}))) {abc})

Return value:
$$$$$$abc

Source:
https://github.com/danielstjules/Stringy#padbothint-length–string-padstr—-

10. Function PadRight
→ Returns a string of a given length such that that the end of the string is padded.

Solution:
(append {abc} (dup {$} (- 20 (length {abc}))))

Return value:
abc$$$$$$$$$$$$$$$$$

Source:
https://github.com/danielstjules/Stringy#padbothint-length–string-padstr—-

11. Function PadBoth
→ Return a string of a given length such that both sides of the string string are padded.

Requirement:
→ In addition: length padding left and length padding right can be unequal, but you should make it equal!

Example:
[new-string-length] = 10 and length [input] = 7 -> X1234567X and not XX1234567X

Solution:
(append (dup {X} (/ (- 10 (length {1234567})) 2) ) {1234567} (dup {X} (/ (- 10 (length {1234567})) 2) ))

Return value:
X1234567X

Source:
https://github.com/danielstjules/Stringy#padbothint-length–string-padstr—-

12. Function RemoveLeft
→ Returns a new string with the [prefix] removed, if present. Here [prefix] is “foo”.

Solution:
(if (starts-with {foobar} {foo}) (slice {foobar} (length {foo})))

Return value:
bar

Source:
https://github.com/danielstjules/Stringy#padbothint-length–string-padstr—-

13. Function RemoveRight
→ Returns a new string with the [suffix] removed, if present. Here [suffix] is “bar”.

Solution:
(if (ends-with {foobar} {bar}) (chop {foobar} (length {bar})))

Return value:
foo

Source:
https://github.com/danielstjules/Stringy#padbothint-length–string-padstr—-

14. Function Shuffle
→ Returns a string with its characters in random order.

Solution:
(join (randomize (explode {abcdefg})))

Return value could be:
cgbfead

Source:
https://github.com/danielstjules/Stringy#shuffle

15. Function TrimLeft
→ Returns a string with a specific character (here: -) removed from the start of the input.

Solution:
(trim {—-abc———} {-} {})

Return value:
abc———

Source:
https://github.com/danielstjules/Stringy#trimleft-string-chars

16. Function TrimRight
→ Returns a string with with a specific character (here: -) removed from the end of the input.

Solution:
(trim {—-abc———} {} {-})

Return value:
—-abc

Source:
https://github.com/danielstjules/Stringy#trimright-string-chars

17. Function TrimBoth
→ Returns a string with a specific character removed from the start and end of the string. Here: – from the beginning and = from the end.

Solution:
(trim {—abc=====} {-} {=})

Return value:
abc

Source:
https://github.com/danielstjules/Stringy#trim-string-chars

18. Function Upper-case-first
→ Converts the first character of the supplied string to upper case.

Solution:
(title-case {abc})

Return value:
Abc

Source:
https://github.com/danielstjules/Stringy#swapcase

19. Function Upper-case-all
→ Converts the first character of each word in the supplied string to upper case.

Solution:
(join (map title-case (parse {This is the end!})) { })

Return value:
This Is The End!

Explanation function 2 Camelize

(first (parse (lower-case {CAMEL_cASE}) {_|-} 0 ))

; the result is “camel”, which is a string
; the number 0 is necessary due to the regular expression {_|-}

; find now the second part:

(rest (parse (lower-case {CAMEL_cASE}) {_|-} 0))

; the result is (“case”), which is a list
; to convert it to a string, use apply:

(apply string (rest (parse (lower-case {CAMEL_cASE}) {_|-} 0)))

; the result is “case”, which is a string
; uppercase now the first character

(title-case (apply string (rest (parse (lower-case {CAMEL_cASE}) {_|-} 0))))

;to glue both results, use the function append which accept strings as parameters:

(append
(first (parse (lower-case {CAMEL-cASE}) {_|-} 0 ))
(title-case (apply string (rest (parse (lower-case {CAMEL-cASE}) {_|-} 0)))))

Much easier than it looks, right!

A (shorter) regex solution is:

(replace {([_-]{1})([a-zA-Z]{1})} (lower-case {CAMEL-cASE}) (upper-case $2) 0)

$0 matches ‘-c’, $1 ‘-‘ and $2 ‘c’ (in this example). You could replace [a-zA-Z] with the metacharacter \w

B. Intermediate level

; define a data structure: name – gender – score
(setq mc-data-students ‘((John Male 6) (Tim Male 8) (Grace Female 4) (Suzanna Female 7)))
-> ((John Male 6) (Tim Male 8) (Grace Female 4) (Suzanna Female 7))

; extract all scores
(setq mc-scores (flat (find-all ‘(* ?) mc-data-students (rest (rest $it)))))
→ (6 8 4 7)

; how many scores above 5?
(length (find-all 5 mc-scores $it <))
→ 3

; average all students
(div (apply ‘+ (flat (find-all ‘(* * *) mc-data-students (rest (rest $it))))) $count)
→ 6.25

; average all female students
(div (apply ‘+ (flat (find-all ‘(* Female *) mc-data-students (rest (rest $it))))) $count)
→ 5.5

; average all students with score > 5
(div (apply ‘+ (find-all 5 mc-scores $it <)) $count)
→ 7

I hope that you’ll be inspired by the wonderful possibilities of newLISP. Implementing the code in VisualNEO is very easy, thanks to the excellent plugin of Hans-Peter Wickern: https://visualneo.com/product/hpwnewlisp.

Thank you for reading. Till next time!

Reinier Maliepaard

(last update: 09-11-2019)