I'm trying to get a visually clear output of my program:
a = -1234
b = 1234
#printf "a = %s%1.2e" "" a
#printf "b = %s%1.2e" " " b
which gives:
a = 1.23e+03
b = -1.23e+03
(The point is to add an extra space for positive number)
Now I want to automate it. I tried to write a funtion:
function negspace(x::Number)
if x < 0
return "", x
else
return " ", x
end
end
and print with
a = -1234
b = 1234
#printf "a = %s%1.2e" negspace( a )
#printf "b = %s%1.2e" negspace( b )
Even simpler is to use the printf format flag to do this directly by putting a space after the %:
julia> #sprintf("a = % 1.2e", -1234)
"a = -1.23e+03"
julia> #sprintf("b = % 1.2e", 1234)
"b = 1.23e+03"
Found a way:
#!/usr/bin/env julia
function signspace(x::Number)
if x > 0
return #sprintf(" %1.2e", x)
else
return #sprintf( "%1.2e", x)
end
end
a = -1234
b = 1234
println("a = ", signspace(a))
println("b = ", signspace(b))
but I'm not sure it is optimal.
Related
I am trying out Base.rsplit() for the first time and I was surprised to see that the order of the data does not change when I use split vs rsplit. See this example:
julia> my_string = "Hello.World.This.Is.A.Test"
"Hello.World.This.Is.A.Test"
julia> a = split(my_string, ".")
6-element Vector{SubString{String}}:
"Hello"
"World"
"This"
"Is"
"A"
"Test"
julia> b = rsplit(my_string, ".")
6-element Vector{SubString{String}}:
"Hello"
"World"
"This"
"Is"
"A"
"Test"
julia> a == b
true
This is a bit counterintuitive given that rsplit says:
Similar to split, but starting from the end of the string.
rsplit just goes from the right side and the only practical difference is the limit parameter.
Try typing in Julia:
#less rsplit("txt",".")
You will find the following function:
function _rsplit(str::AbstractString, splitter, limit::Integer, keepempty::Bool, strs::Array)
n = lastindex(str)::Int
r = something(findlast(splitter, str)::Union{Nothing,Int,UnitRange{Int}}, 0)
j, k = first(r), last(r)
while j > 0 && k > 0 && length(strs) != limit-1
(keepempty || k < n) && pushfirst!(strs, #inbounds SubString(str,nextind(str,k)::Int,n))
n = prevind(str, j)::Int
r = something(findprev(splitter,str,n)::Union{Nothing,Int,UnitRange{Int}}, 0)
j, k = first(r), last(r)
end
(keepempty || n > 0) && pushfirst!(strs, SubString(str,1,n))
return strs
end
I am trying to convert a program written in Python to Julia. I have been using Julia for the last 2 hours.
My code is the following:
function spin_add(buff,clust,spins,padd)
if size(buff) == 0
return(clust)
else
i = buff[1][1] #row
j = buff[1][2]] #column
L = size(spins[1:1,:])
u = i-1
d = i+1
r = j+1
l = j-1
if i == L
d = 1
end
if i == 1
u = L
end
if j == L
r = 0
end
if j == 1
l = L
end
nei = [(u,j),(d,j),(i,r),(i,l)]
popfirst!(buff)
for site in nei
if site not in clust
if spins[site] == spins[i,j]
if rand() < padd
push(clust,site)
push(buff,site)
end
end
end
end
return(spin_add(buff, clust, spins, padd))
end
end
However, I am getting an error that says that an end is not added. The exact error is
syntax: "if" at In[10]:2 expected "end", got "]"
Stacktrace:
[1] top-level scope
# In[10]:6
[2] eval
# .\boot.jl:360 [inlined]
[3] include_string(mapexpr::typeof(REPL.softscope), mod::Module, code::String, filename::String)
# Base .\loading.jl:1116
I do not understand where I must add the end.
j = buff[1][2]-->]<-- #column
Taking out that extra "]" should solve it.
I have a string. I want to (a) keep "/" in fractions, (b) insert whitespace around "/" that are between words, and (c) remove all other "/".
s = "/// // / 1/2 111/222 a/b abc/abc a / b / // ///"
The result should be as follows.
s = "1/2 111/222 a b abc abc a b"
I have tried a few things. I cannot make everything right.
I'm not a regex expert, but this appears to work on your example.
s = "/// // / 1/2 111/222 a/b abc/abc a / b / // ///"
i <- gsub("/{2,}|/\\s", "", s)
i <- trimws(gsub("([[:alpha:]]{1,})(/)([[:alpha:]]{1,})", "\\1 \\3", i))
i <- gsub("\\s{2,}", " ", i)
identical(i, "1/2 111/222 a b abc abc a b")
[1] TRUE
Referring to this question from Wilmott Forums, I've just written the following function:
Public Function KmeansPrice(ByVal priceArray As Range, _
ByVal clustersNumber As Integer) As Double
' Following rows are reproducible only if RExcel has been installed
' on your Excel!
Dim y() As Double
RInterface.StartRServer
RInterface.PutArrayFromVBA "x", priceArray
RInterface.PutArrayFromVBA "n", clustersNumber
RInterface.RRun "x = as.numeric(x)"
RInterface.RRun "cluster = kmeans(x, n)$cluster"
RInterface.RRun "bestBid = rep(NA, n)"
RInterface.RRun "for(i in 1:n)" & _
"{" & _
" assign(paste('group.', i, sep = ''), " & _
" x[cluster == i]);" & _
" bestBid[i] = max(get(paste('group.', i, sep = '')))" & _
"}"
RInterface.RRun "y = min(bestBid) + 0.01"
y = RInterface.GetArrayToVBA("y")
KmeansPrice = y(0, 0)
End Function
Of course I've prototyped it in R before and it worked properly, then I guess that the cause of this error:
Error -2147220501
in Module RExcel.RServer
Error in variable assignment
is related to the wrong usage of RInterface.GetArrayToVBA() for what concerns dimensions and indexing of arrays from R to VBA.
Is anyone able to make the code above work? A working example with an array of just five or ten elements as priceArray and clustersNumber equal to 2 or 3 would be sufficient.
I'm not familiar with the clustering function, but this returns a result without breaking.
I prefer to make my functions in an R editor and then source the code, so I did this in R, then sourced my R function.
kmeansPrice <- function(priceArray,clustersNumber)
{
`[` <- function(...) base::`[`(...,drop=FALSE) #in case we have a 1 dimensional table
x<-priceArray
n<- clustersNumber
x<-matrix(as.numeric(x),nrow=dim(x)[1],ncol=dim(x)[2])
cluster = kmeans(x, n)$cluster
bestBid = rep(NA, n)
for(i in 1:n)
{
assign(paste('group.', i, sep = ''),
x[cluster == i])
bestBid[i] = max(get(paste('group.', i, sep = '')))
}
return(min(bestBid) + 0.01)
}
Then you can just
Public Function KmeansPrice(ByVal priceArray As Range, _
ByVal clustersNumber As Integer) As Double
rinterface.PutArrayFromVBA "priceArray", priceArray.Value 'I think this ".Value" was your problem'
rinterface.PutArrayFromVBA "clustersNumber", clustersNumber
rinterface.RRun "theResult <- kmeansPrice(priceArray,clustersNumber)"
y = rinterface.GetRExpressionValueToVBA("theResult") 'preferred to GetArrayToVBA for single-value results'
KmeansPrice = y
End Function
and run it with example data: a 2x4 table that evaluates to
[,1] [,2]
[1,] 5 9
[2,] 6 10
[3,] 7 11
[4,] 8 12
with 3 "clusters"
Sub runkmeans()
theResult = KmeansPrice(Range("BH2:BI5"), 3)
MsgBox (theResult)
End Sub
which yields 6.01
Let's say I have an input file where each line contains the path from the root (A) to a leaf
echo "A\tB\tC\nA\tB\tD\nA\tE" > lines.txt
A B C
A B D
A E
How can I easily generate the resulting tree?: (A(B(C,D),E))
I'd like to use GNU tools (awk, sed, etc.) because they tend to work better with large files, but an R script would also work. The R input would be:
# lines <- lapply(readLines("lines.txt"), strsplit, " +")
lines <- list(list(c("A", "B", "C")), list(c("A", "B", "D")), list(c("A","E")))
In Perl:
#!/usr/bin/env perl
use strict;
my $t = {};
while (<>) {
my #a = split;
my $t1 = $t;
while (my $a = shift #a) {
$t1->{$a} = {} if not exists $t1->{$a};
$t1 = $t1->{$a};
}
}
print &p($t)."\n";
sub p {
my ($t) = #_;
return
unless keys %$t;
return '('
. join(',', map { $_ . p($t->{$_}) } sort keys %$t)
. ')';
}
This script returns:
% cat <<EOF | perl l.pl
A B C
A B D
A E
EOF
(A(B(C,D),E))
Note that this script, due to recursion in p is not at all suited for large datasets. But that can be easily resolved by turning that into a double for loop, like in the first while above.
Why do it the easy way, if you can use Bourne Shell script instead? Note, this is not even Bash, this is plain old Bourne shell, without arrays...
#!/bin/sh
#
# A B C
# A B D
# A E
#
# "" vs "A B C" -> 0->3, ident 0 -> -0+3 -> "(A(B(C"
# "A B C" vs "A B D" -> 3->3, ident 2 -> -1+1 -> ",D"
# "A B D" vs "A E" -> 3->2, ident 1 -> -2+1 -> "),E"
# "A E" vs. endc -> 2->0, ident 0 -> -2+0 -> "))"
#
# Result: (A(B(C,D),E))
#
# Input stream is a path per line, path segments separated with spaces.
process_line () {
local line2="$#"
n2=$#
set -- $line1
n1=$#
s=
if [ $n2 = 0 ]; then # last line (empty)
for s1 in $line1; do
s="$s)"
done
else
sep=
remainder=false
for s2 in $line2; do
if ! $remainder; then
if [ "$1" != $s2 ]; then
remainder=true
if [ $# = 0 ]; then # only children
sep='('
else # sibling to an existing element
sep=,
shift
for s1 in $#; do
s="$s)"
done
fi
fi
fi
if $remainder; then # Process remainder as mismatch
s="$s$sep$s2"
sep='('
fi
shift # remove the first element of line1
done
fi
result="$result$s"
}
result=
line1=
(
cat - \
| sed -e 's/[[:space:]]\+/ /' \
| sed -e '/^$/d' \
| sort -u
echo '' # last line marker
) | while read line2; do
process_line $line2
line1="$line2"
test -n "$line2" \
|| echo $result
done
This produces the correct answer for two different files (l.sh is the shell version, l.pl the version in Perl):
% for i in l l1; do cat $i; ./l.sh < $i; ./l.pl < $i; echo; done
A
A B
A B C D
A B E F
A G H
A G H I
(A(B(C(D),E(F)),G(H(I))))
(A(B(C(D),E(F)),G(H(I))))
A B C
A B D
A E
(A(B(C,D),E))
(A(B(C,D),E))
Hoohah!
Okay, so I think I got it:
# input
lines <- c(list(c("A", "B", "C")), list(c("A", "B", "D")), list(c("A","E")))
# generate children
generate_children <- function(lines){
children <- list()
for (line in lines) {
for (index in 1:(length(line)-1)){
parent <- line[index]
next_child <- line[index + 1]
if (is.null(children[[parent]])){
children[[parent]] <- next_child
} else {
if (next_child %notin% children[[parent]]){
children[[parent]] <- c(children[[parent]], next_child)
}
}
}
}
children
}
expand_children <- function(current_parent, children){
if (current_parent %in% names(children)){
expanded_children <- sapply(children[[current_parent]], function(current_child){
expand_children(current_child, children)
}, USE.NAMES = FALSE)
output <- setNames(list(expanded_children), current_parent)
} else {
output <- current_parent
}
output
}
children <- generate_children(lines)
root <- names(children)[1]
tree <- expand_children(root, children)
dput(tree)
# structure(list(A = structure(list(B = c("C", "D"), "E"), .Names = c("B",""))), .Names = "A")
Is there a simpler answer?