Is it possible to extend class for limited types only? - crystal-lang

I would like to add normalize method to Arrays of Numbers only (Float & Int) as it doesn't make sense for String. But it won't compile, is that possible?
class Array(Number)
def normalize
multiplier = 1 / max
map{ |v| multiplier * v }
end
end
p [1, 2].normalize

This is not possible, as I'm sure you've seen. As such, you have two options.
1) You can extend the class into a new one that just uses the type you want.
class NumberArray < Array(Number)
# Do something
end
The obvious downside being that you can't use an Array(Number) as a NumberArray.
2) You can write a guard clause around the normalize method that checks the array type and makes sure it's a number array.
class Array(T)
def normalize
{% unless T < Number %}
{% raise "Expected Number type for Array#normalize, got #{T}" %}
{% end %}
multiplier = 1 / max
map { |v| multiplier * v }
end
end

Related

How can I write an efficient loop to solve this Code Wars problem?

The problem is the following:
This is a problem taken from code wars and titled 'Is my friend cheating?'
. A friend of mine takes a sequence of numbers from 1 to n (where n > 0).
. Within that sequence, he chooses two numbers, a and b.
. He says that the product of a and b should be equal to the sum of all numbers in the sequence, excluding a and b.
. Given a number n, could you tell the numbers he excluded from the sequence?
The function takes the parameter: n (n is always strictly greater than 0) and returns an array or a string of the form:
It happens that there are several possible (a, b). The function returns an empty array (or an empty string) if no possible numbers are found which will prove that my friend has not told the truth!
Example of returned sequence:
removNb(26) should return [(15, 21), (21, 15)]
I have tried a simple loop sequence:
def remov_nb(n):
somme = 0
liste = []
for num in range (n+1):
somme += num
for a in range(n+1):
for b in range(n+1):
if a * b == (somme-a-b):
liste.append((a,b))
return (liste)
and also used itertools:
def remov_nb(n):
from itertools import product
liste = []
somme = sum(x for x in range(1,n+1))
for x,y in product(range(1,n+1), range(1,n+1)):
if (somme - x - y) == (x * y):
liste.append((x,y))
return liste
The function doesn't work on Code Wars for lack of efficiency.
Can someone guide me here?

Understanding & Converting ThinkScripts CompoundValue Function

I'm currently converting a ThinkScript indicator to C#, however, I've run into this CompoundValue function and I'm unsure how to covert it.
The documents reads :
Calculates a compound value according to following rule: if a bar
number is greater than length then the visible data value is returned,
otherwise the historical data value is returned. This function is used
to initialize studies with recursion.
Example Use:
declare lower;
def x = CompoundValue(2, x[1] + x[2], 1);
plot FibonacciNumbers = x;
My interpretation:
Based on description and example. It appears we are passing a calculation in x[1] + x[2] and it performing this calculation on the current bar and the previous bar (based on first param of 2). I'm unsure what the parameter 1 is for.
My Question:
Please explain what this function is actually doing. If possible, please illustrate how this method works using pseudo-code.
For the TLDR; crowd, some simple code that hopefully explains what the CompoundValue() function is trying to do, and which might help in converting it's functionality:
# from: Chapter 12. Past/Future Offset and Prefetch
# https://tlc.thinkorswim.com/center/reference/thinkScript/tutorials/Advanced/Chapter-12---Past-Offset-and-Prefetch
# According to this tutorial, thinkScript uses the highest offset, overriding
# all lower offsets in the script - WOW
declare lower;
# recursive addition using x[1] is overridden by 11 in the plot for
# Average(close, 11) below; SO `x = x[1] + 1` becomes `x = x[11] + 1`
def x = x[1] + 1;
# using CompoundValue, though, we can force the use of the *desired* value
# arguments are:
# - length: the number of bars for this variable's offset (`1` here)
# - "visible data": value to use IF VALUES EXIST for a bar (a calculation here)
# - "historical data": value to use IF NO VALUE EXISTS for a bar (`1` here)
def y = CompoundValue(1, y[1] + 1, 1);
# *plotting* this Average statement will change ALL offsets to 11!
plot Average11 = Average(close, 11);
# `def`ing the offset DOES NOT change other offsets, so no issue here
# (if the `def` setup DID change the offsets, then `x[1]` would
# become `x[14]`, as 14 is higher than 11. However, `x[1]` doesn't change.
def Average14 = Average(close, 14);
plot myline = x;
plot myline2 = y;
# add some labels to tell us what thinkScript calculated
def numBars = HighestAll(BarNumber());
AddLabel(yes, "# Bars on Chart: " + numBars, Color.YELLOW);
AddLabel(yes, "x # bar 1: " + GetValue(x, numBars), Color.ORANGE);
AddLabel(yes, "x # bar " + numBars + ": " + x, Color.ORANGE);
AddLabel(yes, "y # bar 1: " + GetValue(y, numBars), Color.LIGHT_ORANGE);
AddLabel(yes, "y # bar " + numBars + ": " + y, Color.ORANGE);
Now, some, er, lots of details...
First, a quick note on "offset" values:
thinkScript, like other trading-related languages, uses an internal looping system. This is like a for loop, iterating through all the "periods" or "bars" on a chart (eg, 1 bar = 1 day on a daily chart; 1 bar = 1 minute on a 1 minute intraday chart, etc). Every line of code in thinkScript is run for each and every bar in the chart or length of time specified in the script.
As noted by the OP, x[1] represents an offset of one bar before the current bar the loop is processing. x[2] represents two bars before the current bar, and so on. Additionally, it's possible to offset into the future by using negative numbers: x[-1] means one bar ahead of the current bar, for example.
These offsets work similarly to the for loop in C#, except they're backwards: x[0] in C# would represent the current x value, as it would in thinkScript; however, moving forward in the loop, x[1] would be the next value, and x[-1] wouldn't exist because, well, there is no past value before 0. (In general, of course! One can definitely loop with negative numbers in C#. The point is that positive offset indices in thinkScript represent past bars, while negative offset indices in thinkScript represent future bars - not the case in C#.)
Also important here is the concept of "length": in thinkScript, length parameters represent the distance you want to go - like the offset, but a range instead of one specific bar. In my example code above, I used the statement plot Average11 = Average(close, 11); In this case, the 11 parameter represents plotting the close for a period of 11 bars, ie, offsets x[0] through x[10].
Now, to explain the CompoundValue() function's purpose:
The Chapter 12. Past/Future Offset and Prefetch thinkScript tutorial explains that thinkScript actually overrides smaller offset or length values with the highest value in a script. What that means is that if you have two items defined as follows:
def x = x[1] + 1;
plot Average11 = Average(close, 11);
thinkScript will actually override the x[1] offset with the higher length used in the Average statement - therefore causing x[1] to become x[11]!
Yike! That means that the specified offsets, except the highest offset, mean nothing to thinkScript! So, wait a minute - does one have to use all the same offsets for everything, then? No! This is where CompoundValue() comes in...
That same chapter explains that CompoundValue() allows one to specify an offset for a variable that won't be changed, even if a higher offset exists.
The CompoundValue() function, with parameter labels, looks like this:
CompoundValue(length, "visible data", "historical data")
As the OP noted, this isn't really particularly clear. Here's what the parameters represent:
length: the offset number of bars for this variable.
In our example, def x = x[1] + 1, there is a 1 bar offset, so our statement starts as CompoundValue(length=1, ...). If instead, it was a larger offset, say 14 bars, we'd put CompoundValue(length=14, ...)
"visible data": the value or calculation thinkScript should perform if DATA IS AVAILABLE for the current bar.
Again, in our example, we're using a calculation of x[1] + 1, so CompoundValue(length=1, "visible data"=(x[1] + 1), ...). (Parentheses around the equation aren't necessary, but may help with clarity.)
"historical data": the value to use if NO DATA IS AVAILABLE for the current bar.
In our example, if no data is available, we'll use a value of 1.
Now, in thinkScript, parameter labels aren't required if the arguments are in order and/or defaults are supplied. So, we could write this CompoundValue statement like this without the labels:
def y = CompoundValue(1, y[1] + 1, 1);
or like this with the labels:
def y = CompoundValue(length=1, "visible data"=(y[1] + 1), "historical data"=1);
(Note that parameter names containing spaces have to be surrounded by double quotes. Single-word parameter names don't need the quotes. Also, I've placed parens around the equation just for the sake of clarity; this is not required.)
In summary: CompoundValue(...) is needed to ensure a variable uses the actual desired offset/number of bars in a system (thinkScript) that otherwise overrides the specified offsets with a higher number if present.
If all the offsets in a script are the same, or if one is using a different programming system, then CompoundValue() can simply be broken down into its appropriate calculations or values, eg def x = x[1] + 1 or, alternatively, an if/else statement that fills in the values desired at whatever bars or conditions are needed.
Please let me provide two equivalent working versions of the code in thinkscript itself. We use this approach to prove equivalence by subtracting the equivalent outputs from each other - the result should be 0.
# The original Fibonacci code with a parameter "length" added.
# That parameter is the first parameter of the CompoundValue function.
declare lower;
def length = 2;
def x = CompoundValue(length, x[1] + x[2], 1);
# plot FibonacciNumbers = x;
# Equivalent code using the `if` statement:
def y;
if(BarNumber() > length){
# Visible data. This is within the guarded branch of the if statement.
# Historical data y[1] (1 bar back) and y[2] (2 bars back) is available
y = y[1] + y[2];
}else{
# Not enough historical data so we use the special case satisfying the
# original rule.
y = 1;
}
plot FibonacciNumbersDiff = y - x;
Thinkscript "recursion" is a somewhat inflated term. The function name CompoundValue is not very helpful so it may create confusion.
The version using the if statement is more useful in general because when walking through the time series of bars, we often need a program structure with multiple nested if statements - this cannot be done with the CompoundValue function. Please see my other articles which make use of this in the context of scanning.
In Java, using the same structure, it looks like this:
int size = 100;
int length = 2;
int[] values = new int[size];
for(int index = 1; index < size; index++){
if(index > length){
values[index] = values[index - 1] + values[index - 2];
}else{
values[index] = 1;
}
}
The fundamental difference is the for loop which is not present in the thinkscript code. thinkscript provides the loop in a kind of inversion of control where it executes user code multiple times, once for each bar.

Rule out solutions in pyomo

New to pyomo and python in general and I am trying to implement a simple solution to a binary integer programming problem. However the problem is large but a large percentage of the values of the matrix x are known in advance. I have been trying to figure out how to 'tell' pyomo that some values are known in advance and what they are.
from __future__ import division # converts to float before division
from pyomo.environ import * # Make symbolds used by pyomo known to python
model = AbstractModel() # Declaration of an abstract model, called model
model.users = Set()
model.slots = Set()
model.prices=Param(model.users, model.slots)
model.users_balance=Param(model.users)
model.slot_bounds=Param(model.slots)
model.x = Var(model.users, model.slots, domain=Binary)
# Define the objective function
def obj_expression(model):
return sum(sum(model.prices[i,j] * model.x[i,j] for i in model.users)
for j in model.slots)
model.OBJ = Objective(rule=obj_expression, sense=maximize)
# A user can only be assigned to one slot
def one_slot_rule(model, users):
return sum(model.x[users,n] for n in model.slots) <= 1
model.OneSlotConstraint = Constraint(model.users, rule=one_slot_rule)
# Certain slots have a minimum balance requirement.
def min_balance_rule1(model, slots):
return sum(model.x[n,slots] * model.users_balance[n] for n in
model.users) >= model.slot_bounds[slots]
model.MinBalanceConstraint1 = Constraint(model.slots,
rule=min_balance_rule1)
So I want to be able to benefit from the fact that I know certain values of x[i,j] to be 0. So for example I have a list of extra conditions
x[1,7] = 0
x[3,6] = 0
x[5,8] = 0
How do I include this information in order to benefit from reducing the search space?
Many Thanks.
After the model is constructed you can do the following:
model.x[1,7].fix(0)
model.x[3,6].fix(0)
model.x[5,8].fix(0)
or, assuming that you have a Set, model.Arcs, that contains the following:
model.Arcs = Set(initialize=[(1,7), (3,6), (5,8)])
you can fix x variables in a loop:
for i,j in model.Arcs:
model.x[i,j].fix(0)

Count value in template expression

I want to count a value inside a template expression, in Xtend, without printing it out.
This is my code:
def generateTower(Tower in) {
var counter = 0.0;
'''
One Two Three Four
«FOR line : in.myTable»
«counter» «line.val1» «line.val2» «line.val3»
«counter = counter + 1»
«ENDFOR»
'''
}
So this will generate a table with four columns, whereas the first column is incremented starting at 0.0. The problem is, that «counter = counter + 1» is printed as well. But I want the expression above to just count up, without printing it out.
What could be the best solution to solve this problem?
You could use this simple and readable solution:
«FOR line : in.myTable»
«counter++» «line.val1» «line.val2» «line.val3»
«ENDFOR»
If you insist on the separate increment expression, use a block with null value. This works because the null value is converted to empty string in template expressions (of course you could use "" as well):
«FOR line : in.myTable»
«counter» «line.val1» «line.val2» «line.val3»
«{counter = counter + 1; null}»
«ENDFOR»
Although the first solution is the better. If you require complex logic in a template expression I recommend implementing it by methods not by inline code...
And finally, here is a more OO solution for the problem:
class TowerGenerator {
static val TAB = "\t"
def generateTower(Tower in) {
var counter = 0
'''
One«TAB»Two«TAB»Three«TAB»Four
«FOR line : in.myTable»
«generateLine(line, counter++)»
«ENDFOR»
'''
}
def private generateLine(Line line, int lineNumber) '''
«lineNumber»«TAB»«line.val1»«TAB»«line.val2»«TAB»«line.val3»
'''
}
Xtend is a full-fledged programming language. You can write Java-like expressions and templates. The problem there is that you're inside a triple quote (template), and everything you write there gets outputted. You can count inside the loop, but take into account that you're counting the elements in the in.myTable collection, and this can be obtained using in.myTable.length. So count could be calculated beforehand as in.myTable.length.
«{counter = counter + 1; null}» definitely worked. But as a recommendation, since it is java, writing it as «{counter++; null}» should do the trick as well. It helps because, you may need to modify your code and you can also put it in front as in: ++counter - by putting the operator first, the compiler takes a number, adds one to it before reading the value.

python and weierstrass function

based on this function. I'm trying to create two empty arrays (one for x and other for y), which later I will use to plot in python. But before anything this is what I have so far...
import math
x1=-2.0
x2=2.0
arr1 = []
arr2 = []
i=0
n=10
delta=(x2-x1)/n
for i in range (0,n+1):
x=x1+delta*i
arr1.append(x)
print arr1
# I have not called the w function yet
the code above creates a list of 10 numbers for now to keep it simple. Then it will send the elements of the array to the function below and compute the equation with certain numbers(infinite loop).
#This function will create the array list for y
import math
def w(x, limit):# the limit here to compare when the number is really small
suma = 0.0
sumb = 0.0
m=1
x=0
suma=suma+((1/(math.pow(2,m))*(math.sin(math.pow(2,m)*x)))
sumb=suma+((1/(math.pow(2,m+1))*(math.sin(math.pow(2,m+1)*x))) # I'm having a
#syntax error
#here
x+=0
if (abs (suma-sumb)<limit):
break:
else m+=1:
if (m<20):
break:
I will appreciate any help with my syntax errors or any suggestion. I just hope I was clear enough.
Thanks ahead of time
The syntax error is actually on the previous line, where the parenthesis are not balanced. You need an extra ) at the end of that line (and at the one you indicated as giving an error too btw).
There are also a few other issues
suma is set to zero, so suma = suma + ... is the same as suma = ..., but I'm guessing you still need to add while loop before this line.
On the line indicated, you have sumb = suma +, which is probably a copy/paste mistake.
The code block starting at x+=0 is indented by only 3 spaces instead of 4. This is probably not the case in your actual code, but if it is, Python will complain about that too.
else m+=1: should be else: m+=1 (colon directly after else, not at the end of the line.
break: should just be break (without to colon).