Let's say I have a struct like this:
(struct house (bedrooms bathrooms address price))
How can I create a sub-struct for, say, houses with 3 bedrooms and 2 bathrooms?
(struct 3-2-house house
; ???
; somehow fill in bedrooms=3 and bathrooms=2
; ???
)
(define house-on-apple-street (3-2-house "123 apple street" 100000))
It seems something like #:auto is called for here but it's not clear how to apply #:auto to fields inherited from parent struct ...
Thanks!
Related
Background
I have a data vector, called STRUCT_A that contains the following structs. Each of these structs have sub values that are populated from a Jenkins build at random. Below is an example of one instance of this data vector:
BEGIN STRUCT for STRUCT_A
somemember_: 4
anothermember_: 3
location_: "New York"
END STRUCT for STRUCT _A
BEGIN STRUCT for STRUCT_A
somemember_: 6
anothermember_: 123
location_: "South Bend"
END STRUCT for STRUCT_A
BEGIN STRUCT for STRUCT_A
somemember_: 10
anothermember_: 6
location_: "Baton Rouge"
END STRUCT for STRUCT_A
You can access any particular member with the following syntax: STRUCT_A.anothermember(2) will return 123 for example.
Problem and attempted solution
I want to find the very first struct where a 1 occurs in the anothermember_: member, then return the value of somemember_ in that very same struct. I have done some research on the find command, but this focuses on members of one vector. My situation deals with structs that have multiple members. Below is the closest example of what I am trying to do:
The picture above shows a 4-by-4 magic square matrix called X. What I am trying to do in the example above is find the first 2 in the matrix, which in this case is located at position five. Where this 2 is located will change each time the Jenkins build is run. The example above deals with the first half of my broader issue. However, I am not sure how to translate this method into a struct, hence my question...
Question
How do I find the first struct where a a particular member of said struct has a specific value?
A possible solution:
% Reproduction example
a = struct('somemember_',1);
b = struct('somemember_',2);
c = struct('somemember_',2);
struct_array = [a b c];
elementOfInterest = 2;
% Find index of first occurence of element of interest in the struct array
find([struct_array.somemember_] == elementOfInterest,1)
returns
2
Let's say I have red and green baskets holding boxes of strawberries and grapes:
public class Basket {
public enum Color { RED, GREEN };
private Color color;
private List<FruitBox> fruitBoxes;
//Assume appropriate constructors, getters exist
}
public class FruitBox {
public enum Fruit { STRAWBERRY, GRAPE };
private Fruit fruit;
//Assume appropriate constructors, getters exist
}
And I need to use Drools to print the following calculations:
The number of GRAPE or STRAWBERRY FruitBoxes in a Basket if it exceeds two
The total number of FruitBoxes, grouped on FruitBox fruit and Basket Color
How might I code (1.) and (2.) as simple and efficient Drools rules? After reading the documentation, I have come up with the following solutions:
rule "Two or more of same fruit in any Basket"
when
//Bind the contents of each basket
$Basket : Basket($FruitBoxes : fruitBoxes)
//Compute A list of the unique fruits in current basket contents
$fruits : Object() from accumulate( FruitBox($f : fruit) from $FruitBoxes, collectSet($f) )
//Match and bind each unique fruit one by one
$fruit : FruitBox.Fruit() from $fruits
//Find the number of times the unique fruit occurs in this Basket
$count : Number(intValue >= 2) from accumulate(
$f : FruitBox(fruit == $fruit) from $FruitBoxes,
count($f) )
then
System.out.println($Basket + " has " + $count + " of the fruit " + $fruit);
end
Which successfully prints, for one test dataset, output like:
com.sample.DroolsTest$Basket#10cd6753 has 4 of the fruit STRAWBERRY
com.sample.DroolsTest$Basket#10cd6753 has 3 of the fruit GRAPE
com.sample.DroolsTest$Basket#2e060819 has 2 of the fruit GRAPE
My concern is that my rule is long and complicated, and appears to iterate each Basket several times (once to find the unique fruits within, and then once more to tally each fruit). I suspect that this is a product of my lack of Drools knowledge and that a better solution exists. In plain Java, I would use a HashMap to store each fruit and its count in one pass, which would be simple and fast. Is there any way to rewrite my Drools code to improve performance and readability? The same question applies to my second rule:
rule "Totals by fruit and by basket color"
when
//Calculate the cross product of all fruits and colors
$fruit : FruitBox.Fruit()
$color : Basket.Color()
//Count the number of FruitBoxes of the chosen fruit in Baskets of the chosen color
$count : Number() from accumulate(
$fb : FruitBox(fruit == $fruit)
and exists Basket(color == $color, fruitBoxes contains $fb),
count($fb) )
then
System.out.println($count + " " + $fruit + " in " + $color + " baskets");
end
Which produces output like:
5 STRAWBERRY in GREEN baskets
6 STRAWBERRY in RED baskets
6 GRAPE in GREEN baskets
4 GRAPE in RED baskets
but, unfortunately, looks like it searches through all the Baskets for every FruitBox, when it would make far more sense to tally up one (or all) kind(s) of FruitBoxes while iterating over the Baskets once. Is there a better syntax for this rule as far as performance is concerned?
Thanks for the help!
Hi for the first question I would use two separate rules:
rule "strawberriesInBasket"
dialect "mvel"
when
$basket : Basket($fruitBoxes : fruitBoxes)
Number($count : intValue() > 2) from accumulate ($fruitBox : FruitBox(fruit.name == "strawberry") from $fruitBoxes, count($fruitBox))
then
System.out.println("Count of strawberry boxes in basket is: " + $count )
end
and
rule "grapesInBasket"
dialect "mvel"
when
$basket : Basket($fruitBoxes : fruitBoxes)
Number($count : intValue() > 2) from accumulate ($fruitBox : FruitBox(fruit.name == "grape") from $fruitBoxes, count($fruitBox))
then
System.out.println("Count of grape boxes in basket is: " + $count )
end
Please notice I changed the enum Fruit to data object with field name.
I am trying something (in netlogo), but it is not working. I want a value of a position from a list of numbers. And I want to use the number that comes out of it to retrieve a name from a list of names.
So if I have a list like [1 2 3 4] en a list with ["chicken" "duck" "monkey" "dog"]
I want my number 2 to correspond with "duck".
So far, my zq is a list of numbers and my usedstrategies is a list of names.
let m precision (max zq) 1
let l position m zq
let p (position l zq) usedstrategies
But when I try this the result will be false, because l is not part of usedstrategies.
Ideas?
You need the item primitive to select from the list after matching on the other list. I am not sure what the precision line is for. However, here is a self contained piece of code that I think demonstrates what you want to do. Note that NetLogo counts positions from 0, not 1. I also used arbitrary numbers in the list so you don't get confused between the number in the list and its position.
to testme
let usedstrategies (list "chicken" "duck" "monkey" "dog")
let zq (list 5 6 7 8)
let strategynum position 7 zq
let thisstrategy item strategynum usedstrategies
type "Selected strategy number " type strategynum
type " which is " print thisstrategy
end
Jen's solution is perfectly fine, but I think this could also be a good use case for the table extension. Here is an example:
extensions [table]
to demo
let usedstrategies ["chicken" "duck" "monkey" "dog"]
let zq [5 6 7 8]
let strategies table:from-list (map list zq usedstrategies)
; get item corresponding with number 7:
print table:get strategies 7
end
A "table", here, is a data structure where a set of keys are associated with values. Here, your numbers are the keys and the strategies are the values.
If you try to get an item for which there is no key in the table (e.g., table:get strategies 9), you'll get the following error:
Extension exception: No value for 9 in table.
Here is a bit more detail about how the code works.
To construct the table, we use the table:from-list reporter, which takes a list of lists as input and gives you back a table where the first item of each sublist is used as a key and the second item is used as a value.
To construct our list of lists, we use the map primitive. This part is a bit more tricky to understand. The map primitive needs two kind of inputs: one or more lists, and a reporter to be applied to elements of these lists. The reporter comes first, and the whole expression needs to be inside parentheses:
(map list zq usedstrategies)
This expression "zips" our two lists together: it takes the first element of zq and the first element of usedstrategies, passes them to the list reporter, which constructs a list with these two elements, and adds that result to a new list. It then takes the second element of zq and the second element of usedstrategies and does the same thing with them, until we have a list that looks like:
[[5 "chicken"] [6 "duck"] [7 "monkey"] [8 "dog"]]
Note that the zipping expression could also have be written:
(map [ [a b] -> list a b ] zq usedstrategies)
...but it's a more roundabout way to do it. The list reporter by itself is already what we want; there is no need to construct a separate anonymous reporter that does the same thing.
I have tried the code.
DEFINE VARIABLE totalbalance AS DECIMAL NO-UNDO.
DEFINE FRAME f1
WITH CENTERED THREE-D SIZE 100 BY 50.
FOR EACH customer NO-LOCK BREAK BY country WITH FRAME f1:
ACCUMULATE balance(TOTAL BY country).
IF FIRST-OF(customer.country) THEN
DISPLAY customer.country.
DISPLAY customer.state customer.balance.
IF LAST-OF(customer.country) THEN
DO:
DISPLAY SKIP FILL("-", 25) AT 50 FORMAT "x(25)".
DISPLAY ACCUM TOTAL customer.balance AT 51.
DISPLAY SKIP FILL("-", 25) AT 50 FORMAT "x(25)".
END.
END.
It only gives total balance per country but I also want to display total balance per state.
You do not have a "break by state" so it will do nothing by state.
Something like this (not very tested):
define frame f1
with
centered
.
for each customer no-lock break by country by state with frame f1:
accumulate balance( total by country ).
accumulate balance( sub-total by state ).
if first-of( customer.country ) then
display customer.country.
if first-of( customer.state ) then
display customer.state.
display customer.balance.
if last-of( customer.country ) then
do:
display skip fill( "-", 25 ) at 50 format "x(25)".
display accum total customer.balance at 51.
display skip fill( "-", 25 ) at 50 format "x(25)".
end.
if last-of( customer.state ) then
do:
display skip fill( "-", 25 ) at 80 format "x(25)".
display accum sub-total customer.balance at 81.
display skip fill( "-", 25 ) at 80 format "x(25)".
end.
end.
(That probably doesn't actually work... but the multiple BY clauses are the main thing that you are missing.)
Personally I find the ACCUM syntax to be unpleasant and not worth bothering with. I usually just create and manage simple variables. I find that sort of coding to be much cleaner. So unless this is a "gotchya" question on a skills test I strongly suggest that you avoid coding in this manner. If it is a "gotchya" question move on to a more suitable prospective employer -- you don't want to work for anyone who thinks that this is a good idea.
I would do it more like this:
define variable countryBalance as decimal no-undo.
define variable stateBalance as decimal no-undo.
for each customer no-lock break by country by state with frame f1:
if first-of( customer.country ) then
do:
display customer.country.
countryBalance = 0.
end.
if first-of( customer.state ) then
do:
display customer.state.
statebalance = 0.
end.
assign
countryBalance = countryBalance + customer.balance
stateBalance = stateBalance + customer.balance
.
display customer.balance.
if last-of( customer.country ) then
do:
display countryBalance.
end.
if last-of( customer.state ) then
do:
display stateBalance.
end.
end.
I think that is a whole lot easier to read, understand and maintain.
i know that there are many ways to program a deck of poker cards where value is important after searching on the net.
My problem is that my "deck" of cards is a simple array with value as "card name" (example 1 = Ace of Spades)
Do i randomize my current Array with NSMutableArray and then remove index 0 everytime the card is being "drawn" til the last card?"
The standard algorithm is something like this:
a) Populate an array of 52 cards (order not important)
b) Set size variable to 52
c) Pick a random number r in range 0 <= r < size
d) Store the picked card, card[r], as the result
e) Swap card[r] and card[size - 1]
f) decrement size
g) goto c