Compilation error, undefined function in Elixir - compilation

I am making a poker hand analyzer in Elixir. The program takes an input of 52 ints and distributes 5 odd (indexed) cards to player1 and 5 even (indexed) cards to player2, before deciding whose hand is better. I made a function for each player (below). When I try and compile, compiler throws an error: (CompileError) poker.ex:49: undefined function player1/1. I have tried a lot of things, but they all seem to fail, please help!
defmodule Poker do
decks = %{ 1 => "2C", 2 => "3C", 3 => "4C", 4 => "5C", 5 => "6C", 6 => "7C", 7 => "8C",
8=> "9C", 9=> "10C", 10 => "11C", 11 => "12C", 12 => "13C", 13 => "1C", 14 => "2D",
15 => "3D", 16=> "4D", 17 => "5D", 18=> "6D", 19=> "7D", 20=> "8D", 21=> "9D",
22=> "10D", 23=> "11D", 24=> "12D", 25=> "13D", 26=> "1D", 27=> "2H", 28=> "3H",
29=> "4H", 30=> "5H", 31=> "6H", 32=> "7H", 33=> "8H", 34=> "9H", 35=> "10H",
36=> "11H", 37=> "12H", 38=> "13H", 39=> "1H", 40=> "2S", 41=> "3S", 42=> "4S",
43=> "5S", 44=> "6S", 45=> "7S", 46=> "8S", 47=> "9S", 48=> "10S", 49=> "11S",
50=> "12S", 51=> "13S", 52=> "1S"}
defp player1(cards), do: Enum.take(Enum.drop_every(cards, 2), 5)
defp player2(cards) do
Enum.take(
cards -- (Enum.drop_every(cards, 2)) ,5)
end
mapHand = for n <- player1(cards), do: Map.get(decks, n)
end
What am I doing wrong?

There's some problems with your code. And the solution mostly depends on what you want to do. It would help you a great deal to take a look at https://elixir-lang.readthedocs.io/en/latest/technical/scoping.html to get a better understanding of the scoping rules in Elixir.
The most straightforward solution I would suggest in your case, would be to replace all of the matches e.g.mapHand = for n <- ... for functions. Like so:
defmodule Poker do
defp decks do
%{ 1 => "2C", 2 => "3C", 3 => "4C", 4 => "5C", 5 => "6C", 6 => "7C", 7 => "8C",
8=> "9C", 9=> "10C", 10 => "11C", 11 => "12C", 12 => "13C", 13 => "1C", 14 => "2D",
15 => "3D", 16=> "4D", 17 => "5D", 18=> "6D", 19=> "7D", 20=> "8D", 21=> "9D",
22=> "10D", 23=> "11D", 24=> "12D", 25=> "13D", 26=> "1D", 27=> "2H", 28=> "3H",
29=> "4H", 30=> "5H", 31=> "6H", 32=> "7H", 33=> "8H", 34=> "9H", 35=> "10H",
36=> "11H", 37=> "12H", 38=> "13H", 39=> "1H", 40=> "2S", 41=> "3S", 42=> "4S",
43=> "5S", 44=> "6S", 45=> "7S", 46=> "8S", 47=> "9S", 48=> "10S", 49=> "11S",
50=> "12S", 51=> "13S", 52=> "1S"}
end
defp player1(cards), do: Enum.take(Enum.drop_every(cards, 2), 5)
defp player2(cards) do
Enum.take(cards -- (Enum.drop_every(cards, 2)), 5)
end
def map_hand(cards) do
for n <- player1(cards), do: Map.get(decks(), n )
end
end
That way you could then (outside of the module) do something like:
player_1_cards = [1, 2, 3, 4, 5]
Poker.map_hand(player_1_cards)
And get something like:
["3C", "5C"]

Related

How to bulk update table in Laravel?

I have a database table with the following columns:
columnindex | type | id
1 1 1
2 2 1
3 3 1
I have a input array:
$arr = [1 => 2, 2 => 5, 3 => 6,...]
As result I need this:
columnindex | type | id
1 2 1
2 5 1
3 6 1
How to use update bulk in this case?
I tried this but it is not optimized:
$arr = [1 => 2, 2 => 5, 3 => 6];
foreach($arr as $columnindex => $type) {
SessionPrepared::where("id", 1)->where("columnindex", $columnindex)->update(["type" => $type]);
}
You are looking for the upsert method (https://laravel.com/docs/9.x/eloquent#upserts).
Example:
SessionPrepared::upsert([
['id' => 1, 'columnindex' => 1, 'type' => 'value'],
['id' => 2, 'columnindex' => 2, 'type' => 'value'],
['id' => 3, 'columnindex' => 3, 'type' => 'value'],
], ['id', 'columnindex'], ['type']);
Results in it bulk updating the column type for the provider identifiers id & columnindex

sync fetch eloquent laravel

i have this array:
$ingredients_alergens = [
1285 => [ //id from ingredient
4, //id from alergen
2
]
1286 => [
6
]
1287 => [
1
]
1288 => [
9
]
]
and i want make a massive sync similar to this:
$ingredient->alergens()->sync([1,3,8]);
but with all the array. I want make a Ășnic sync/upsert/something for a full list and don't do query to query. Because i have arrays/jsons from more than a thousand redords.
Are there any way to build a massive sync (into single query, like an upsert) into eloquent laravel?
You have many Ingredients (1285, 1286, 1287, 1288), so you'd need to get all of them first and then, for each of them, sync the relationship.
You could do it with these 2 lines using your $ingredients_alergens variable:
$ingredients_alergens = [
1285 => [4, 2],
1286 => [6],
1287 => [1],
1288 => [9],
];
Ingredient::findMany(array_keys($ingredients_alergens)) // findMany([1285, 1286, 1287, 1288])
->each(fn(Ingredient $i) => $i->alergens()->sync($ingredient_alergens[$i->id]));
If you do not want sync to delete existing alergens. (For example, you just want to add alergen 9 to ingredient 1288), use syncWithoutDetaching() instead of sync().

Adding missing rows of data in a collection - unexplanable Laravel behavior

I have a table of data and I need to fetch an array from it, that looks like this:
[
['Mon', 25],
['Tue', 13],
['Thu', 25]
]
I'm achieving this through some collection acrobatics. At some point I am mapping the collection adding the numerical value of that day (1 Monday, 2 Tuesday) as a key, so I can sortKeys() later.
The problem is not all days are always present and I want to add them with a value of 0 at their respective place.
My first attempt was foreach on an array of days of the week, and if
$collection->flatten()->search($day) returns false, prepend that day. This works fine, but Thu always get appended. It never returns true on the search even though it's copied and pasted and should be identical. All other days are skipped/prepended correctly...
Then I tried array_search on toArray() and the same thing happened. Thu never returns true ...
This is extremely weird, basically Thu == Thu returns false
Is there anyway I can use array_merge or something like that to make it better (or get it working at all?).
This is one way of doing it. It could be done much cleaner, if your data was structured different in the first place, like using day name/value as key, instead of having both in sub arrays, but I will keep to the original question:
$defaultDays = collect([
['Mon', 0],
['Tue', 0],
['Wed', 0],
['Thu', 0],
['Fri', 0],
['Sat', 0],
['Sun', 0],
]);
$days = [
['Mon', 25],
['Tue', 13],
['Thu', 25]
];
// Use $defaultDays to map, as we will need all seven days no matter what.
$days = $defaultDays->map(static function (array $defaultDay) use ($days) {
// Current match is the default day...
$match = $defaultDay;
foreach ($days as $day) {
if ($day[0] === $defaultDay[0]) {
$match = $day;
}
}
return $match;
});
This will result in:
Illuminate\Support\Collection {#1388
#items: array:7 [
0 => array:2 [
0 => "Mon"
1 => 25
]
1 => array:2 [
0 => "Tue"
1 => 13
]
2 => array:2 [
0 => "Wed"
1 => 0
]
3 => array:2 [
0 => "Thu"
1 => 25
]
4 => array:2 [
0 => "Fri"
1 => 0
]
5 => array:2 [
0 => "Sat"
1 => 0
]
6 => array:2 [
0 => "Sun"
1 => 0
]
]
}

laravel Maatwebsite validate sum multi column

hi im using Maatwebsite with laravel everything working so good so far ..
but i want to update excel like this ..
number date amount
1 2020-01-01 10
1 2020-01-01 -5
1 2020-01-01 -5
2 2020-02-02 20
2 2020-02-02 -20
3 2020-03-03 50
3 2020-03-03 -50
3 2020-03-03 40
3 2020-03-03 -40
what i want thats the sum of the amount with number 1 sould return 0 or end the import
number date amount
1 2020-01-01 10
1 2020-01-01 -5
1 2020-01-01 -5
how can i check this (10 + -5 + -5 == 0) or fail
and for 2 and 3 ect ..
thanks a lot
I explained all the steps in comments but I will explain here as well.
When you loop through each row, you first need to grab all the rows where number field is 1, 2 or 3, what ever the number is currently in the iteration.
In this case, the first loop results will be:
number date amount
1 2020-01-01 10
1 2020-01-01 -5
1 2020-01-01 -5
Then you sum (add up) the values from the amount column.
In this case, it will sum like this:
10
-5
-5
-----
0
If the answer is not 0, take the current sheet ($sheet) and return what you currently have, to be exported.
Full class:
...
use Maatwebsite\Excel\Concerns\FromArray;
class ExampleExport implements FromArray
{
public function array() : array
{
// EXAMPLE hardcoded data for the purpose of this demo
$rows = [
[
'number' => 1,
'date' => '2020-01-01',
'amount' => 10
],
[
'number' => 1,
'date' => '2020-01-01',
'amount' => -5
],
[
'number' => 1,
'date' => '2020-01-01',
'amount' => -5
],
[
'number' => 2,
'date' => '2020-02-02',
'amount' => 20
],
[
'number' => 2,
'date' => '2020-02-02',
'amount' => -20 // <-------- Change this to -21 to test
],
[
'number' => 3,
'date' => '2020-03-03',
'amount' => 50
],
[
'number' => 3,
'date' => '2020-03-03',
'amount' => -50
],
[
'number' => 3,
'date' => '2020-03-03',
'amount' => 40
],
[
'number' => 3,
'date' => '2020-03-03',
'amount' => -40
],
];
// EXAMPLE hardcoded data for the purpose of this demo
$rows = collect($rows);
// You probably going to get this from your database so should look like this:
// $rows = \App\Model::all(['number', 'date', 'amount']); // OR below
// $rows = DB::table('examples')->select(['number', 'date', 'amount'])->get();
// Blank sheet
$sheet = [];
foreach ($rows as $row) {
// Get all the rows where the `number` field has the same value,
// for example 1, 2, or 3, then sum the `amount` field (add up).
//
// If the amount does not add up to 0, stop and return what you currently got
if ($rows->where('number', $row['number'])->sum('amount') !== 0) {
return $sheet;
}
// Else, add them to the sheet and continue.
$sheet[] = $row;
}
return $sheet;
}
}
Results:
When amount adds up to 0:
When amount does not add up to 0:

tcl array to ruby hash parser

I have a file outputted from a TCL script, which has a TCL syntax'ed array, as below.
set data(item1) {
xyz {
a { one two three 1 2 3}
b { three one two 3 2 4}
}
lmn {
z { "something" 1 2 3}
d { "samething" 3 2 4}
}
};
set data(item2) {
xyz {
ss { 100 }
sd { "sdss" 200 300}
}
lmn {
ee { "xdf" 1 "2dsd" 3}
pp { "dd" "fsdf" 3 2 4}
}
};
Now I need to read this file in a Ruby program and build them into a Hash of Hashes, similar to something below, before I start consuming the required data:
data = {
'item1' => {
'xyz' => {
'a' => %w{one two three 1 2 3},
'b' => %w{three one two 3 2 4}
},
'lmn' => {
'z' => %w{something 1 2 3},
'd' => %w{samething 3 2 4}
}
},
'item2' => {
'xyz' => {
'ss' => %w{100 },
'sd' => %w{sdss 200 300}
},
'lmn' => {
'ee' => %w{xdf 1 2dsd 3},
'pp' => %w{dd fsdf 3 2 4}
}
}
}
Is there any Ruby utility or method that I can use for this purpose?
Thanks in advance for your support.
No. You will have to build a parser. Take a look at treetop.
It will help a lot to have some early basic knowledge of compilers like compiling phases (lexical analyzer and syntax analyzer, you don't need semantic analyzer for this project).
Also, some basic understanding of grammars will help, since is pre-requisite for compilers - but most likely you will stumble upon grammars while trying to figure out compilers.

Resources