Hi I have this json file with these partial data, and I will be user 1 in this example, and need to create a graph vertex and connect it to my user for all my friends and then create a vertex and connect my friend friends and so on.
[
{
"id": 1,
"name": "Me",
"friends": [25, 24, 16, 8, 13, 12, 7, 15]
},
{
"id": 2,
"name": "Anne Emerson",
"friends": [3, 21, 4, 20, 24, 5, 7, 12, 18]
},
{
"id": 3,
"name": "Ashley Hopper",
"friends": [2, 22, 10, 20, 25, 11]
},
{
"id": 4,
"name": "Alba Gates",
"friends": [2, 17, 21, 11, 7, 13]
},
{
"id": 5,
"name": "Louise Pennington",
"friends": [2, 23, 22, 15, 20, 24]
},
{
"id": 6,
"name": "Shields Gilliam",
"friends": [26]
},
{
"id": 7,
"name": "Freida Evans",
"friends": [1, 4, 2, 9, 18, 17]
},
{
"id": 8,
"name": "Noel Serrano",
"friends": [1, 24, 18, 9, 16, 11, 23]
}
]
I tried to write a recursion function that goes throw my field list which are users with these ID's [3, 21, 4, 20, 24, 5, 7, 12, 18] like in the example. and create a graph vertex for the User I'm at and connect it with its parent user. and keeps going throw all my friends first then goes throw my friend friends and so on until I discovered all of the friends related to my user weather its directly or indirectly.
Graph methods to use:
create a parent vertex (ME):
let me = graph.createVertex(data: "Me")
connect vertexes together:
graph.add(.undirected, from: me, to: user25, weight: 1)
User model:
struct User: Codable, Identifiable, Hashable {
enum CodingKeys: CodingKey {
case id
case name
case friends
}
var id: Int
var name: String
var friends: [Int]
}
what I tried so far using nested loops:
for (index, i) in friends.enumerated() {
print("i: \(i)")
let getUserByID = datas.users.filter{ $0.id == index}
for (index, i) in getUserByID.enumerated() {
print(i.friends)
}
}
where friends is let friends = [25, 24, 16, 8, 13, 12, 7, 15]
The logic isn't hitting me yet and I wasn't able to achieve this in Swift 5 can anyone help ?
Sample OutPut for my friends mutual list:
John Doe - edge distance: 2, Mutual friends: 5
Bob Kemp - edge Distance: 2, Mutual friends: 3
Bryce Holmes - edge Distance: 3
James Smith - edge Distance: 3
The list should be ranked firstly by edge distance and secondly
by number of mutual friends.
I am using Google Charts API for my Data Visualisations. I would like to retrieve the date of the selected day on the Chart.
What I retrieve is quite strange.. I am using a selectHandler on the chart as recommended by documentation.
function selectHandler() {
console.log(chart.getSelection()[0]);
}
google.visualization.events.addListener(chart, 'select', selectHandler);
On clicking following date, I am reading following output on console:
22/04/2020 : 1587513600000
19/06/2020 : 1592524800000
What kind of date format is this?
Can anyone help me?
this is the date represented as the number of milliseconds since the Unix Epoch.
it is the same value as returned by the getTime() method on a date object.
you can pass the value received from the selection to the date constructor to get the date...
var selection = chart.getSelection();
if (selection.length > 0) {
var selectedDate = new Date(selection[0].date);
}
see following working snippet...
google.charts.load('current', {
packages: ['calendar']
}).then(function () {
var dataTable = new google.visualization.DataTable();
dataTable.addColumn({ type: 'date', id: 'Date' });
dataTable.addColumn({ type: 'number', id: 'Won/Loss' });
dataTable.addRows([
[ new Date(2012, 3, 13), 37032 ],
[ new Date(2012, 3, 14), 38024 ],
[ new Date(2012, 3, 15), 38024 ],
[ new Date(2012, 3, 16), 38108 ],
[ new Date(2012, 3, 17), 38229 ],
[ new Date(2013, 9, 4), 38177 ],
[ new Date(2013, 9, 5), 38705 ],
[ new Date(2013, 9, 12), 38210 ],
[ new Date(2013, 9, 13), 38029 ],
[ new Date(2013, 9, 19), 38823 ],
[ new Date(2013, 9, 23), 38345 ],
[ new Date(2013, 9, 24), 38436 ],
[ new Date(2013, 9, 30), 38447 ]
]);
var chart = new google.visualization.Calendar(document.getElementById('calendar_basic'));
var options = {
title: "Red Sox Attendance",
height: 350,
};
function selectHandler() {
var selection = chart.getSelection();
if (selection.length > 0) {
var selectedDate = new Date(selection[0].date);
console.log(selectedDate);
}
}
google.visualization.events.addListener(chart, 'select', selectHandler);
chart.draw(dataTable, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="calendar_basic"></div>
note: you should check the length of the selection before accessing the contents.
the select event is also called when a date is un-selected.
in this case the selection array will be empty...
I am working on N-Queens problem and to check whether the queen has been already placed on upper and lower left diagonals, I am finding difficulty in formulating for loop condition.
func isPlaceable(row: Int, column: Int) -> Bool {
// check if one same row another queen exits
for i in 0..<column {
if (solution[row][i] == 1) {
return false
}
}
// check upper left diagonal
// in C or C++ I can do
// for (int i = row, int j = col; i >= 0 && j >= 0; i--, j--) {
// if (board[i][j])
// return false;
//}
}
What would be Swifty way of doing it i.e. Combing the two condition?
One possible solution is you can use zip(_:_:) with two sequence.
func isPlaceable(row: Int, column: Int) -> Bool {
// check if one same row another queen exits
for i in 0..<column {
if (solution[row][i] == 1) {
return false
}
}
// check upper left diagonal
let seq1 = (0...row).reversed()
let seq2 = (0...column).reversed()
for (i,j) in zip(seq1, seq2) {
if (board[i][j]) {
return false
}
}
//your code
}
var i = row
var j = col
while (i >= 0 && j >= 0) {
if (board[i][j])
return false;
i -= 1
j -= 1
}
This type of process benefits a lot from double indirection and prepared matrices.
For example, you could give an identifier to each line segment on the board and check that no two queens use the same line segment.
There are 46 line segments on a standard chess board:
8 vertical
8 horizontal
30 diagonals (15 each)
(I numbered them 1 through 46)
When the queens are properly placed, they will each use 4 line segments (axes) that no other queen uses. Sets are the ideal structure to check for this non intersecting union. By preparing a matrix with a Set of 4 axis identifiers at each row/column, a simple union of the sets for the 8 queens will tell us if they align with each other.
// vertical axes (1...8)
let vAxis = [ [ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ],
[ 1, 2, 3, 4, 5, 6, 7, 8 ]
]
// horizontal axes (9...16)
let hAxis = [ [ 9, 9, 9, 9, 9, 9, 9, 9 ],
[ 10, 10, 10, 10, 10, 10, 10, 10 ],
[ 11, 11, 11, 11, 11, 11, 11, 11 ],
[ 12, 12, 12, 12, 12, 12, 12, 12 ],
[ 13, 13, 13, 13, 13, 13, 13, 13 ],
[ 14, 14, 14, 14, 14, 14, 14, 14 ],
[ 15, 15, 15, 15, 15, 15, 15, 15 ],
[ 16, 16, 16, 16, 16, 16, 16, 16 ],
]
// up right axes (17...31)
let uAxis = [ [ 17, 18, 19, 20, 21, 22, 23, 24 ],
[ 18, 19, 20, 21, 22, 23, 24, 25 ],
[ 19, 20, 21, 22, 23, 24, 25, 26 ],
[ 20, 21, 22, 23, 24, 25, 26, 27 ],
[ 21, 22, 23, 24, 25, 26, 27, 28 ],
[ 22, 23, 24, 25, 26, 27, 28, 29 ],
[ 23, 24, 25, 26, 27, 28, 29, 30 ],
[ 24, 25, 26, 27, 28, 29, 30, 31 ],
]
// down right axes (32...46)
let dAxis = [ [ 39, 40, 41, 42, 43, 44, 45, 46 ],
[ 38, 39, 40, 41, 42, 43, 44, 45 ],
[ 37, 38, 39, 40, 41, 42, 43, 44 ],
[ 36, 37, 38, 39, 40, 41, 42, 43 ],
[ 35, 36, 37, 38, 39, 40, 41, 42 ],
[ 34, 35, 36, 37, 38, 39, 40, 41 ],
[ 33, 34, 35, 36, 37, 38, 39, 40 ],
[ 32, 33, 34, 35, 36, 37, 38, 39 ],
]
// Set of axis numbers for each [row][col] of the board
let axes = (0..<8).map()
{
row in (0..<8).map()
{ Set([ vAxis[row][$0], hAxis[row][$0], uAxis[row][$0], dAxis[row][$0] ]) }
}
// position of each queen ( column number at each row )
var queenCols = [5, 3, 6, 0, 7, 1, 4, 2]
// Check if each queen in queenCols is on its own 4 axes
// We will have 32 (8 x 4) different axes used if no queen aligns with another
let fullCover = queenCols.enumerated()
.reduce(Set<Int>()){ $0.union(axes[$1.0][$1.1]) }
.count == 32
This "fullCover" check can be used in a brute force loop on all 16,777,216 combinations or it can be refined to perform incremental checks in an optimized search tree. (BTW the brute force solution takes only 80 seconds to compute on a MacBook Pro)
So, in the end, you can avoid for loops altogether.
[EDIT] function to find the 92 solutions in a brute force loop:
public func queenPositions() -> [[Int]]
{
var result : [[Int]] = []
let rows : [Int] = Array(0..<8)
for i in 0..<16777216
{
var N:Int = i
let queenCols = rows.map{ _ -> Int in let col = N % 8; N = N / 8; return col}
let fullCover = queenCols.enumerated()
.reduce(Set<Int>()){ $0.union(axes[$1.0][$1.1]) }
.count == 32
if fullCover { result.append(queenCols) }
}
return result
}
[EDIT2] Using the set matrices in an optimized tree search produces the 92 solutions in 0.03 second.
Here is the optimized (and generic) function:
public func queenPositions2(boardSize:Int = 8) -> [[Int]]
{
let vAxis = (0..<boardSize).map{ _ in (0..<boardSize).map{$0} }
let hAxis = (0..<boardSize).map{ Array(repeating:$0+boardSize, count:boardSize) }
let uAxis = (0..<boardSize).map{ row in (0..<boardSize).map{ 2 * boardSize + row + $0} }
let dAxis = (0..<boardSize).map{ row in (0..<boardSize).map{ 5 * boardSize - row + $0} }
let axes = (0..<boardSize).map()
{
row in (0..<boardSize).map()
{ Set([ vAxis[row][$0], hAxis[row][$0], uAxis[row][$0], dAxis[row][$0] ]) }
}
var result : [[Int]] = []
var queenCols : [Int] = Array(repeating:0, count:boardSize)
var colAxes = Array(repeating:Set<Int>(), count:boardSize)
var queenAxes = Set<Int>()
var row = 0
while row >= 0
{
if queenCols[row] < boardSize
{
let newAxes = axes[row][queenCols[row]]
if newAxes.isDisjoint(with: queenAxes)
{
if row == boardSize - 1
{
result.append(queenCols)
queenCols[row] = boardSize
continue
}
else
{
colAxes[row] = newAxes
queenAxes.formUnion(newAxes)
row += 1
queenCols[row] = 0
continue
}
}
}
else
{
row -= 1
if row < 0 { break }
}
queenAxes.subtract(colAxes[row])
colAxes[row] = Set<Int>()
queenCols[row] += 1
}
return result
}
Given a 10x10 board, the 724 solutions are generated in 0.11 second.
[EDIT3] one liner "for loop" ...
You can generate an array of (row,column) coordinate for the 4 axes of a given position and use that as your data in the for loop:
func isPlaceable(row: Int, column: Int) -> Bool
{
var coverage = (0..<8).map{($0,column)} // horizontal
coverage += (0..<8).map{(row,$0)} // vertical
coverage += zip((max(0,row-column)..<8),(max(0,column-row)..<8)) // diagonal down
coverage += zip((0...min(7,row+column)).reversed(),(max(0,column+row-7)..<8)) // diagonal up
// return !coverage.contains{solution[$0][$1] == 1}
for (r,c) in coverage
{
if solution[r][c] == 1 { return false }
}
return true
}
It feels wasteful to rebuild the whole coverage list every time though. I would compute it once for every coordinate and place it in a row/column matrix for reuse in the isPlaceable() function.
Is there a way to colorize the space between the to lines (Max. Temp and Min. Temp.) in the chart?
#!/usr/local/bin/perl
use warnings;
use 5.014;
use utf8;
use Excel::Writer::XLSX;
my $workbook = Excel::Writer::XLSX->new( 'spreadsheet.xlsx' ) or die $!;
my $worksheet = $workbook->add_worksheet( 'One' );
my $ref = [
[ 'Day', 'Max. Temp.', 'Min. Temp' ],
[ 1, -3.1, -6.4 ],
[ 2, -2.3, -7.2 ],
[ 3, -4.7, -6.8 ],
[ 4, -3.1, -9.5 ],
[ 5, 1.1, -11.4 ],
[ 6, 1.2, 0.3 ],
[ 7, 5.3, 0.7 ],
[ 8, 7.7, 1.5 ],
[ 9, 1.5, -2 ],
[ 10, 1, -1.1 ] ];
$worksheet->write_col( 0, 0, $ref );
my $chart = $workbook->add_chart( type => 'line' );
$chart->set_x_axis( name => 'Day' );
$chart->set_y_axis( name => 'Temperature (° Celsius)' );
$chart->set_style( 11 );
$chart->add_series(
values => [ 'One', 1, $#$ref, 1, 1 ],
name => '=One!$B$1',
);
$chart->add_series(
values => [ 'One', 1, $#$ref, 2, 2 ],
name => '=One!$C$1',
);
I don't think that this feature is available in Excel so it isn't possible in Excel::Writer::XLSX.
At least it isn't available as a single operation in Excel. There are some workarounds, for example here and here, but you don't currently have that level of control in Excel::Writer::XLSX.
Droplines/High-Low lines will be added in a future release. That might be an acceptable workaround.