How to print elements in a vector of vectors - clojure

I have a vector of vectors, and I want to print elements in each vector
I tried the pprint but did not work as wanted
This is the vector of vectors I wish to print:
[["+" "+" "+" "#" "!" "-" "#" "#" "#" "-" "-" "-" "-"]
["!" "#" "+" "+" "+" "#" "+" "+" "+" "-" "#" "#" "-"]
["#" "#" "#" "#" "+" "#" "+" "#" "+" "#" "-" "#" "#"]
["+" "+" "+" "#" "+" "+" "+" "#" "+" "#" "-" "-" "-"]
["+" "#" "+" "#" "#" "#" "#" "+" "+" "-" "#" "#" "-"]
["+" "#" "+" "+" "+" "+" "+" "+" "#" "-" "-" "-" "-"]
["+" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#"]
["+" "+" "+" "+" "+" "+" "+" "+" "+" "+" "+" "+" "#"]]
This is the output I want:
+++#--###--#-
!#+++#+++-##-
####+#+#+#!##
+++#+++#+#!!!
+#+####++!##!
+#++++++#!!!!
+############
++++++++++++#

You can use cl-format to handle list (and list of list in this case) with a control string:
(def input
[["+" "+" "+" "#" "!" "-" "#" "#" "#" "-" "-" "-" "-"]
["!" "#" "+" "+" "+" "#" "+" "+" "+" "-" "#" "#" "-"]
["#" "#" "#" "#" "+" "#" "+" "#" "+" "#" "-" "#" "#"]
["+" "+" "+" "#" "+" "+" "+" "#" "+" "#" "-" "-" "-"]
["+" "#" "+" "#" "#" "#" "#" "+" "+" "-" "#" "#" "-"]
["+" "#" "+" "+" "+" "+" "+" "+" "#" "-" "-" "-" "-"]
["+" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#" "#"]
["+" "+" "+" "+" "+" "+" "+" "+" "+" "+" "+" "+" "#"]])
(use 'clojure.pprint)
(cl-format *out* "~{~{~a~}~%~}" input)
Output:
+++#!-###----
!#+++#+++-##-
####+#+#+#-##
+++#+++#+#---
+#+####++-##-
+#++++++#----
+############
++++++++++++#
Explanation:
~a is the format argument of any type. When enclosed in ~{ and ~}, the format argument will be iterated over a list. So when enclosed twice with ~{ and ~}, ~a will be applied over each element (character) in the nested list. The ~% before the last ~} is to output a newline.
With this, you can easily change the output with control string. For example:
(cl-format *out* "~{~{(~a)~^ ~}~^~%~%~}" input)
(+) (+) (+) (#) (!) (-) (#) (#) (#) (-) (-) (-) (-)
(!) (#) (+) (+) (+) (#) (+) (+) (+) (-) (#) (#) (-)
(#) (#) (#) (#) (+) (#) (+) (#) (+) (#) (-) (#) (#)
(+) (+) (+) (#) (+) (+) (+) (#) (+) (#) (-) (-) (-)
(+) (#) (+) (#) (#) (#) (#) (+) (+) (-) (#) (#) (-)
(+) (#) (+) (+) (+) (+) (+) (+) (#) (-) (-) (-) (-)
(+) (#) (#) (#) (#) (#) (#) (#) (#) (#) (#) (#) (#)
(+) (+) (+) (+) (+) (+) (+) (+) (+) (+) (+) (+) (#)
Note that "~^" is the directive to stop iteration when a list is run out. So "~^<space>" will suppress the space after the last element in each line. And "~^~%~%" will suppress the double newline after the last line.

You don't need any fancy formatting or side-effects (although I do appreciate the information in those answers). Just use clojure.string/join to create the string you want and print it any old way.
> (join "\n" (map join input))
+++#!-###----
!#+++#+++-##-
####+#+#+#-##
+++#+++#+#---
+#+####++-##-
+#++++++#----
+############
++++++++++++#
e.g.
> (let [s (join "\n" (map join input))] (println s))
+++#!-###----
!#+++#+++-##-
####+#+#+#-##
+++#+++#+#---
+#+####++-##-
+#++++++#----
+############
++++++++++++#
nil

We can use run! to go over the outer vector and clojure.string/join to turn each inner vector into a printable string.
Assuming your vector is defined as input:
(require '[clojure.string :as str])
(run! (comp println str/join) input)

Related

Regex for matching a charactor that doesn't have spaces on either side

I have some regex that adds a space on either side of a "\n" return
var regex = new RegExp(r'\n');
final newString = text.replaceAll(regex, " \n ");
However, it keeps adding it as it matches the " \n " also.
How would I match only a return that doesn't have spaces on either side?
How would I match only a return that doesn't have spaces on either side?
Do you mean match if it doesn't have a space on at least one side, or only if it does not have a space on both sides?
That is, do you want to match the newline in "x \ny" or not?
If you want to match a newline which does not have spaces on both sides, you can use:
RegExp(r"(?<! )\n(?! )")
This will match a \n (newline) which is not preceded by a space and not followed by a space. That means "x\ny", but none of "x \ny", "x\n y", and "x \n y".
If you want to match newlines which already have at least one space around them, but not both, you can use the suggestion from #Jerry Jeremiah:
RegExp(r"(?!< )\n|\n(?! )");
This will match "x\ny", "x \ny" and "x\n y", but not "x \n y".
You the replace the match with spaces, even if there is already a space on one side. That side will now have two spaces, which might be unnecessary.
If you want to avoid that, I'd go with a different approach: Match all the newlines, and replace them depending on whether they already have spaces around them:
var newlinesRE = RegExp(r"(?<=([ \n])?)\n(?=( )?)");
String flankNewlinesBySpace(String string) =>
string.replaceAllMapped(newlinesRE, (m) =>
"${m[1] == null ? " " : ""}\n${m[2] == null ? " " : ""}");
This should match every newline, and capture spaces before and after.
It replaces it with a newline. If it does not see a space or newline before, it insert a space before the newline. If it does not see a space after the newline, it inserts one.
(This should ensure that "\n\n" becomes " \n \n ", with only one space between them).
This gives a result of:
"x\ny" ↦ "x \n y"
"x \ny" ↦ "x \n y"
"x\n y" ↦ "x \n y"
"x \n y" ↦ "x \n y"
"x\n\ny" ↦ "x \n \n y"
"x\n \ny" ↦ "x \n \n y"
"x \n\n y" ↦ "x \n \n y"

VB.NET - Regex.Replace error with [ character

I want to remove some characters from a textbox. It works, but when i try to replace the "[" character it gives a error. Why?
Return Regex.Replace(html, "[", "").Replace(",", " ").Replace("]", "").Replace(Chr(34), " ")
When i delete the "[", "").Replace( part it works great?
Return Regex.Replace(html, ",", " ").Replace("]", "").Replace(Chr(34), " ")
The problem is that since the [ character has a special meaning in regex, It must be escaped in order to use it as part of a regex sequence, therefore to escape it all you have to do is add a \ before the character.
Therefore this would be your proper regex code Return Regex.Replace(html, "\[", "").Replace(",", " ").Replace("]", "").Replace(Chr(34), " ")
Because [ is a reserved character that regex patterns use. You should always escape your search patterns using Regex.Escape(). This will find all reserved characters and escape them with a backslash.
Dim searchPattern = Regex.Escape("[")
Return Regex.Replace(html, searchPattern, ""). 'etc...
But why do you need to use regex anyway? Here's a better way of doing it, I think, using StringBuilder:
Dim sb = New StringBuilder(html) _
.Replace("[", "") _
.Replace(",", " ") _
.Replace("]", "") _
.Replace(Chr(34), " ")
Return sb.ToString()

Multiple Patterns in 1 case

In SML, is it possible for you to have multiple patterns in one case statement?
For example, I have 4 arithmetic operators express in string, "+", "-", "*", "/" and I want to print "PLUS MINUS" of it is "+" or "-" and "MULT DIV" if it is "*" or "/".
TL;DR: Is there somewhere I can simplify the following to use less cases?
case str of
"+" => print("PLUS MINUS")
| "-" => print("PLUS MINUS")
| "*" => print("MULT DIV")
| "/" => print("MULT DIV")
Given that you've tagged your question with the smlnj tag, then yes, SML/NJ supports this kind of patterns. They call it or-patterns and it looks like this:
case str of
("+" | "-") => print "PLUS MINUS"
| ("*" | "/") => print "MULT DIV"
Notice the parentheses.
The master branch of MLton supports it too, as part of their Successor ML effort, but you'll have to compile MLton yourself.
val str = "+"
val _ =
case str of
"+" | "-" => print "PLUS MINUS"
| "*" | "/" => print "MULT DIV"
Note that MLton does not require parantheses. Now compile it using this command (unlike SML/NJ, you have to enable this feature explicitly in MLton):
mlton -default-ann 'allowOrPats true' or-patterns.sml
In Standard ML, no. In other dialects of ML, such as OCaml, yes. You may in some cases consider splitting pattern matching up into separate cases/functions, or skip pattern matching in favor of a shorter catch-all expression, e.g.
if str = "+" orelse str = "-" then "PLUS MINUS" else
if str = "*" orelse str = "/" then "MULT DIV" else ...
Expanding upon Ionuț's example, you can even use datatypes with other types in them, but their types (and identifier assignments) must match:
datatype mytype = COST as int | QUANTITY as int | PERSON as string | PET as string;
case item of
(COST n|QUANTITY n) => print Int.toString n
|(PERSON name|PET name) => print name
If the types or names don't match, it will get rejected:
case item of
(COST n|PERSON n) => (* fails because COST is int and PERSON is string *)
(COST n|QUANTITY q) => (* fails because the identifiers are different *)
And these patterns work in function definitions as well:
fun myfun (COST n|QUANTITY n) = print Int.toString n
|myfun (PERSON name|PET name) = print name
;

R Regex number followed by punctuation followed by space

Suppose I had a string like so:
x <- "i2: 32390. 2093.32: "
How would I return a vector that would give me the positions of where a number is followed by a : or a . followed by a space?
So for this string it would be
"2: ","0. ","2: "
The regex you need is just '\\d[\\.:]\\s'. Using stringr's str_extract_all to quickly extract matches:
library(stringr)
str_extract_all("i2: 32390. 2093.32: ", '\\d[\\.:]\\s')
produces
[[1]]
[1] "2: " "0. " "2: "
You can use it with R's built-in functions, and it should work fine, as well.
What it matches:
\\d matches a digit, i.e. number
[ ... ] sets up a range of characters to match
\\. matches a period
: matches a colon
\\s matches a space.

Remove spaces between words of a certain length

I have strings of the following variety:
A B C Company
XYZ Inc
S & K Co
I would like to remove the spaces in these strings that are only between words of 1 letter length. For example, in the first string I would like to remove the spaces between A B and C but not between C and Company. The result should be:
ABC Company
XYZ Inc
S&K Co
What is the proper regex expression to use in gsub for this?
Here is one way you could do this seeing how & is mixed in and not a word character ...
x <- c('A B C Company', 'XYZ Inc', 'S & K Co', 'A B C D E F G Company')
gsub('(?<!\\S\\S)\\s+(?=\\S(?!\\S))', '', x, perl=TRUE)
# [1] "ABC Company" "XYZ Inc" "S&K Co" "ABCDEFG Company"
Explanation:
First we assert that two non-whitespace characters do not precede back to back. Then we look for and match whitespace "one or more" times. Next we lookahead to assert that a non-whitespace character follows while asserting that the next character is not a non-whitespace character.
(?<! # look behind to see if there is not:
\S # non-whitespace (all but \n, \r, \t, \f, and " ")
\S # non-whitespace (all but \n, \r, \t, \f, and " ")
) # end of look-behind
\s+ # whitespace (\n, \r, \t, \f, and " ") (1 or more times)
(?= # look ahead to see if there is:
\S # non-whitespace (all but \n, \r, \t, \f, and " ")
(?! # look ahead to see if there is not:
\S # non-whitespace (all but \n, \r, \t, \f, and " ")
) # end of look-ahead
) # end of look-ahead
Obligatory strsplit / paste answer. This will also get those single characters that might be in the middle or at the end of the string.
x <- c('A B C Company', 'XYZ Inc', 'S & K Co',
'A B C D E F G Company', 'Company A B C', 'Co A B C mpany')
foo <- function(x) {
x[nchar(x) == 1L] <- paste(x[nchar(x) == 1L], collapse = "")
paste(unique(x), collapse = " ")
}
vapply(strsplit(x, " "), foo, character(1L))
# [1] "ABC Company" "XYZ Inc" "S&K Co"
# [4] "ABCDEFG Company" "Company ABC" "Co ABC mpany"
Coming late to the game but would this pattern work for you
(?<!\\S\\S)\\s+(?!\\S\\S)
Demo
Another option
(?![ ]+\\S\\S)[ ]+
You could do this also through PCRE verb (*SKIP)(*F)
> x <- c('A B C Company', 'XYZ Inc', 'S & K Co', 'A B C D E F G Company', ' H & K')
> gsub("\\s*\\S\\S+\\s*(*SKIP)(*F)|(?<=\\S)\\s+(?=\\S)", "", x, perl=TRUE)
[1] "ABC Company" "XYZ Inc" "S&K Co" "ABCDEFG Company"
[5] " H&K"
Explanation:
\\s*\\S\\S+\\s* Would match two or more non-space characters along with the preceding and following spaces.
(*SKIP)(*F) Causes the match the to fail.
| Now ready to choose the characters from the remaining string.
(?<=\\S)\\s+(?=\\S) one or more spaces which are preceded by a non-space , followed by a non-space character are matched.
Removing the spaces will give you the desired output.
Note: See the last element, this regex won't replace the preceding spaces at the first because the spaces at the start isn't preceded by a single non-space character.