Go

Go

Go is an open source programming language initially developed at Google. It is statically-typed, with a syntax loosely derived from C, adding automatic memory management, type safety, some dynamic typing capabilities, additional built-in types such as variable-length arrays and key-value maps, and a large standard library.

Solving a Graph Problem with Go

In this tutorial, we will learn how to solve a Graph Problem with Go. 

During the last couple of days, I have been watching live mocking interviews and even though I am not in the market for a new job (I am very happy at Google), it results interesting to me that so many people struggle with the same problem hidden behind some complicated adornments.

See more at: https://itnext.io/solving-a-graph-problem-with-go-f1049de33856

#go #graph 

Solving a Graph Problem with Go

Resolver Un Problema Gráfico Con Go

En este tutorial, aprenderemos cómo resolver un problema gráfico con Go. 

Durante los últimos días, he estado viendo entrevistas burlonas en vivo y aunque no estoy en el mercado para un nuevo trabajo (estoy muy feliz en Google), me resulta interesante que tantas personas luchan con el mismo problema. escondido detrás de unos complicados adornos.

Uno de los ejemplos de preguntas simuladas decía algo como esto:

Imagine que tiene imágenes y puede duplicar cualquier imagen que desee, creando otra imagen. La nueva imagen (el duplicado) también se puede copiar, y así sucesivamente. Aunque la nueva imagen tiene el mismo aspecto, el nombre es diferente y también puede rastrearlo hasta la imagen principal.

Ahora, queremos eliminar todas las imágenes, pero no podemos eliminar una imagen si tiene duplicados. Debe implementar una función que devuelva el orden en que se pueden eliminar las imágenes.

La función a implementar es la siguiente (estamos usando Go para todo el código en esta publicación):

func deleteOrder(imgs []*Image, cps []*CPOps) []*Image {...}

type Image struct {
  Name string
}// CPOps represent a copy operation. 
type CPOps struct {
  ParentImage *Image //Original images being copied. 
  CpImages []*Image  //Copies of the original image.
}

La función recibe una lista de imágenes y las operaciones de copia entre ellas, luego debe devolver el orden que debemos seguir para eliminar todas las imágenes según la regla anterior.

Veamos un ejemplo:

Images = [A, B, C, D]
CPOps = [
  {ParentImage:A, CPImages:[B, C]},
  {ParentImage:B, CPImages:[D]},
]

Esto quiere decir que A era la imagen original e hicimos dos copias, B y C. Luego hicimos una copia de B en D. La salida de nuestra función deleteOrderdebería ser [D, B, C, A] o [D, C, B, A] o [C, D, B, A]. Tenga en cuenta que son posibles múltiples soluciones, pero todas ellas son tales que cada imagen se elimina solo después de que se eliminan sus copias.

Resolviendo el problema.

Este problema es un algoritmo clásico de clasificación topológica donde se establece algún tipo de dependencia entre objetos. El mismo problema con una redacción diferente se presentó a los candidatos de las entrevistas simuladas, pero en todos los casos, el problema podría reducirse a una clasificación topológica.

La solución que presentamos en esta publicación está escrita para que cada pieza pueda explicarse de forma independiente. Sin embargo, en una entrevista es aceptable escribir un código menos legible por cuestiones de tiempo.

Construyendo el gráfico

Espero que, a estas alturas, el lector pueda darse cuenta de que se trata de un problema gráfico, que a su vez debería ser la primera señal para el entrevistador de que el candidato entiende lo que está pasando.

Si construimos el gráfico usando el ejemplo anterior, deberíamos obtener algo como:

A --> B --> D
 \  
  --> C

Ahora, creemos una función que, dada la entrada, podamos construir un gráfico que se pueda usar para resolver el problema.

type Graph map[string][]string

func buildGraph(imgs []*Image, copos []*CPOps) Graph {
	graph := make(Graph)

	// Add all images to the graph.
	for _, img := range imgs {
		if _, ok := graph[img.Name]; !ok {
			graph[img.Name] = []string{}
		}
	}

	// Add dependencies between images.
	for _, cp := range cpops {
		if _, ok := graph[cp.ParentImage.Name]; !ok {
			graph[cp.ParentImage.Name] = []string{}
		}
		for _, child := range cp.CPImages {
			graph[cp.ParentImage.Name] = append(graph[cp.ParentImage.Name], child.Name)
		}
	}

	return graph
}

Construyendo el gráfico

Tenga en cuenta que primero estamos agregando todos los nodos (imágenes) al gráfico, esto es importante ya que puede haber imágenes que nunca se hayan copiado, por lo tanto, nunca estarán en las relaciones dadas. Luego, establecemos las dependencias entre los nodos.

Ahora, podemos implementar la parte principal del algoritmo, la clasificación topológica.

Clasificación topológica

La ordenación topológica es un DFS simple que atraviesa el gráfico utilizando las dependencias como bordes dirigidos y devuelve el orden inverso. En nuestro caso, estamos interesados ​​en el orden inverso de las dependencias ya que A — > B, necesitamos eliminar B primero, luego A.

func dfs(n string, graph Graph, visited map[string]bool, path []string) []string {
	for _, child := range graph[n] {
		if _, ok := visited[child]; ok {
			continue
		}
		visited[child] = true
		path = dfs(child, graph, visited, path)
	}
	return append(path, n)
}

DFS para recorrer el gráfico dado un nodo inicial.

El DFS atraviesa el gráfico dado un nodo inicial y devuelve las dependencias en orden inverso. La visitedvariable realiza un seguimiento de los nodos que ya hemos visitado en el gráfico (para no repetirlos), y la variable pathrealiza un seguimiento de las dependencias inversas.

Ahora que tenemos una forma de construir el gráfico y recorrerlo, debemos juntar todo a la vez.

// DeletionOrder returns the order the images should be deleted. 
func DeletionOrder((imgs []*Image, cps []*CPOps) []*Image {
	graph := buildGraph(imgs, cps)

	visited := map[string]bool{}
	result := []string{}
	for k := range graph {
		if _, ok := visited[k]; !ok {
			visited[k] = true
			result = dfs(k, graph, visited, result)
		}
	}

	imgsMap := map[string]*Image{}
	for _, img := range imgs {
		imgsMap[img.Name] = img
	}
	imgsOrder := []*Image{}
	for _, name := range result {
		imgsOrder = append(imgsOrder, imgsMap[name])
	}
	return imgsOrder
}

La DeletionOrderfunción construye el gráfico con la entrada dada, para cada nodo que no ha sido visitado dfsse ejecuta. La resultvariable contendrá los nombres de las imágenes en el orden de eliminación correcto.

El resto de la DeleteOrderfunción (línea 14 en adelante) solo se asegura de que seleccionemos las imágenes de los nombres de las imágenes (fuera del algoritmo gráfico).

 

La mayor parte del algoritmo no parece tan complejo y, sin embargo, muchas personas no logran resolver este problema, lo que en mi opinión es factible en una entrevista de 45 minutos. Mi observación es que la mayoría de las personas no identifican ese problema gráfico lo suficientemente rápido como para tener tiempo de implementar una solución funcional.

Otras Consideraciones

El mismo problema puede tomarse en diferentes direcciones dependiendo de cómo quiera mirarlo el entrevistador.

Por ejemplo, la cuestión de escalar el algoritmo, cuando el gráfico tiene miles de nodos, es interesante. Aunque pueden parecer simples, hay algunos casos complicados a considerar.

El problema de detectar si la entrada dada es correcta también podría ser interesante. Para que el gráfico se pueda ordenar, y por lo tanto la ordenación topológica funcione correctamente, el gráfico no debe tener ciclos. Detectar ciclos no es un tema particularmente complejo, pero hacerlo a escala podría ser un poco más problemático.

Estas son preguntas interesantes y el lector debe tomarse un momento para pensar en ellas y en las implicaciones de cada una.

Al final, en una entrevista de 45 minutos, solo hay tiempo disponible para resolver algunos de estos signos de interrogación solo después de que el problema principal se haya codificado correctamente. Sin embargo, esperamos que después de esta publicación, el lector pueda ver algunos problemas y reducirlos fácilmente a esta categoría gráfica de problemas que se pueden resolver usando la ordenación topológica.

 

Buena suerte entrevistando.

Fuente: https://itnext.io/resolving-a-graph-problem-with-go-f1049de33856

#go #graph 

Resolver Un Problema Gráfico Con Go
Hong  Nhung

Hong Nhung

1656693840

Giải Quyết Vấn Đề Đồ Thị Với Go

Trong hướng dẫn này, chúng ta sẽ học cách giải quyết vấn đề về đồ thị với cờ vây. 

Trong vài ngày qua, tôi đã xem trực tiếp các cuộc phỏng vấn chế giễu và mặc dù tôi không tham gia thị trường cho một công việc mới (tôi rất hạnh phúc tại Google), tôi thấy rất thú vị khi có rất nhiều người phải vật lộn với cùng một vấn đề. ẩn sau một số trang điểm phức tạp.

Một trong những câu hỏi mô phỏng ví dụ đã nói điều gì đó như thế này:

Hãy tưởng tượng bạn có hình ảnh và bạn có thể sao chép bất kỳ hình ảnh nào bạn muốn, tạo ra một hình ảnh khác. Hình ảnh mới (bản sao) cũng có thể được sao chép, v.v. Mặc dù hình ảnh mới trông giống nhau, tên khác nhau và bạn cũng có thể theo dõi nó trở lại hình ảnh gốc.

Bây giờ, chúng tôi muốn xóa tất cả các hình ảnh, nhưng chúng tôi không thể xóa một hình ảnh nếu nó có các bản sao. Bạn phải triển khai một hàm trả về thứ tự xóa các hình ảnh.

Hàm để triển khai như sau (chúng tôi đang sử dụng Go cho tất cả mã trong bài đăng này):

func deleteOrder(imgs []*Image, cps []*CPOps) []*Image {...}

type Image struct {
  Name string
}// CPOps represent a copy operation. 
type CPOps struct {
  ParentImage *Image //Original images being copied. 
  CpImages []*Image  //Copies of the original image.
}

Hàm nhận một danh sách các hình ảnh, và các thao tác sao chép giữa chúng, sau đó nó phải trả về thứ tự mà chúng ta phải tuân theo để xóa tất cả các hình ảnh dựa trên quy tắc trên.

Hãy xem một ví dụ:

Images = [A, B, C, D]
CPOps = [
  {ParentImage:A, CPImages:[B, C]},
  {ParentImage:B, CPImages:[D]},
]

Điều này nói rằng A là hình ảnh gốc, và chúng tôi đã tạo hai bản sao, B và C. Sau đó, chúng tôi tạo một bản sao của B thành D. Phần ngoài chức năng của chúng tôi deleteOrderphải là [D, B, C, A] hoặc [D, C, B, A] hoặc [C, D, B, A]. Lưu ý rằng có thể có nhiều giải pháp, nhưng tất cả chúng đều như vậy là mọi hình ảnh chỉ bị xóa sau khi các bản sao của nó bị xóa.

Giải quyết vấn đề.

Bài toán này là một thuật toán sắp xếp theo cấu trúc liên kết cổ điển trong đó một số loại phụ thuộc giữa các đối tượng được thiết lập. Cùng một vấn đề với cách viết khác cũng được đưa ra cho các ứng viên của các cuộc phỏng vấn giả, nhưng trong mọi trường hợp, vấn đề có thể được rút gọn thành Sắp xếp theo cấu trúc liên kết.

Giải pháp mà chúng tôi trình bày trong bài đăng này được viết để mỗi phần có thể được giải thích một cách độc lập. Tuy nhiên, trong một cuộc phỏng vấn được chấp nhận để viết một đoạn mã ít đọc hơn vì lợi ích của thời gian.

Xây dựng đồ thị

Tôi hy vọng rằng bây giờ, người đọc có thể nhận ra đây là một vấn đề về đồ thị, do đó, đây sẽ là tín hiệu đầu tiên cho người phỏng vấn rằng ứng viên hiểu những gì đang diễn ra.

Nếu chúng ta xây dựng biểu đồ bằng cách sử dụng mẫu ở trên, chúng ta sẽ nhận được một cái gì đó như:

A --> B --> D
 \  
  --> C

Bây giờ, hãy tạo một hàm cho đầu vào, chúng ta có thể xây dựng một đồ thị có thể được sử dụng để giải quyết vấn đề.

type Graph map[string][]string

func buildGraph(imgs []*Image, copos []*CPOps) Graph {
	graph := make(Graph)

	// Add all images to the graph.
	for _, img := range imgs {
		if _, ok := graph[img.Name]; !ok {
			graph[img.Name] = []string{}
		}
	}

	// Add dependencies between images.
	for _, cp := range cpops {
		if _, ok := graph[cp.ParentImage.Name]; !ok {
			graph[cp.ParentImage.Name] = []string{}
		}
		for _, child := range cp.CPImages {
			graph[cp.ParentImage.Name] = append(graph[cp.ParentImage.Name], child.Name)
		}
	}

	return graph
}

Xây dựng đồ thị

Lưu ý rằng chúng tôi đang thêm tất cả các nút (hình ảnh) vào biểu đồ trước tiên, điều này rất quan trọng vì có thể có những hình ảnh chưa bao giờ được sao chép, do đó, chúng sẽ không bao giờ nằm ​​trong các quan hệ đã cho. Sau đó, chúng tôi thiết lập sự phụ thuộc giữa các nút.

Bây giờ, chúng ta có thể triển khai phần chính của thuật toán, Sắp xếp theo cấu trúc liên kết.

Sắp xếp theo cấu trúc liên kết

Sắp xếp tôpô là một DFS đơn giản duyệt qua đồ thị bằng cách sử dụng các phụ thuộc là các cạnh có hướng và trả về thứ tự ngược lại. Trong trường hợp của chúng tôi, chúng tôi quan tâm đến thứ tự đảo ngược của các phụ thuộc kể từ A -> B, chúng tôi cần xóa B trước, sau đó A.

func dfs(n string, graph Graph, visited map[string]bool, path []string) []string {
	for _, child := range graph[n] {
		if _, ok := visited[child]; ok {
			continue
		}
		visited[child] = true
		path = dfs(child, graph, visited, path)
	}
	return append(path, n)
}

DFS để duyệt qua đồ thị đã cho một nút ban đầu.

DFS duyệt qua đồ thị đã cho một nút ban đầu và trả về các phụ thuộc theo thứ tự đảo ngược. Biến visitedtheo dõi các nút mà chúng ta đã truy cập trong biểu đồ (để không lặp lại chúng) và biến paththeo dõi các phụ thuộc được đảo ngược.

Bây giờ chúng ta có một cách để xây dựng biểu đồ và duyệt qua nó, chúng ta phải kết hợp mọi thứ lại với nhau cùng một lúc.

// DeletionOrder returns the order the images should be deleted. 
func DeletionOrder((imgs []*Image, cps []*CPOps) []*Image {
	graph := buildGraph(imgs, cps)

	visited := map[string]bool{}
	result := []string{}
	for k := range graph {
		if _, ok := visited[k]; !ok {
			visited[k] = true
			result = dfs(k, graph, visited, result)
		}
	}

	imgsMap := map[string]*Image{}
	for _, img := range imgs {
		imgsMap[img.Name] = img
	}
	imgsOrder := []*Image{}
	for _, name := range result {
		imgsOrder = append(imgsOrder, imgsMap[name])
	}
	return imgsOrder
}

Hàm DeletionOrderxây dựng biểu đồ với đầu vào đã cho, đối với mỗi nút chưa được truy cập, hàm dfssẽ được thực thi. Biến resultsẽ chứa các tên ảnh theo đúng thứ tự xóa.

Phần còn lại của DeleteOrderhàm (dòng 14 trở lên) chỉ là đảm bảo rằng chúng ta chọn ảnh từ tên ảnh (bên ngoài thuật toán đồ thị).

 

Phần lớn thuật toán trông không phức tạp như vậy, nhưng có rất nhiều người không giải được bài toán này, theo ý kiến ​​của tôi là có thể thực hiện được trong một cuộc phỏng vấn 45 phút. Quan sát của tôi là hầu hết mọi người không xác định được vấn đề biểu đồ đó đủ nhanh để có thời gian thực hiện một giải pháp hiệu quả.

Những ý kiến ​​khác

Cùng một vấn đề có thể được đưa ra theo nhiều hướng khác nhau tùy thuộc vào cách người phỏng vấn muốn nhìn nhận vấn đề đó.

Ví dụ, câu hỏi về việc mở rộng thuật toán, khi biểu đồ có hàng nghìn nút, là một câu hỏi thú vị. Mặc dù chúng có thể trông đơn giản, nhưng có một số trường hợp phức tạp cần được xem xét.

Vấn đề phát hiện xem đầu vào đã cho có đúng hay không cũng có thể là một vấn đề thú vị. Để đồ thị có thể sắp xếp được, do đó sắp xếp tôpô hoạt động chính xác, đồ thị không được có chu trình. Việc phát hiện các chu kỳ không phải là một vấn đề đặc biệt phức tạp, nhưng thực hiện nó trên quy mô lớn có thể là một vấn đề khó khăn hơn một chút.

Đây là những câu hỏi thú vị và người đọc nên dành một chút thời gian để suy nghĩ về chúng và ý nghĩa của từng câu hỏi.

Cuối cùng, trong một cuộc phỏng vấn kéo dài 45 phút, chỉ có thời gian trống để giải một vài dấu hỏi trong số này sau khi vấn đề chính đã được mã hóa chính xác. Tuy nhiên, chúng tôi hy vọng rằng sau bài đăng này, người đọc có thể xem xét một số vấn đề và dễ dàng rút gọn chúng thành loại biểu đồ các vấn đề có thể giải được bằng cách sử dụng sắp xếp tôpô.

 

Chúc bạn may mắn khi phỏng vấn.

Nguồn: https://itnext.io/solving-a-graph-problem-with-go-f1049de33856

#go #graph 

Giải Quyết Vấn Đề Đồ Thị Với Go
郝 玉华

郝 玉华

1656693720

用 Go 解决图问题

在本教程中,我们将学习如何使用 Go 解决图问题。 

在过去的几天里,我一直在观看现场模拟面试,尽管我没有在市场上寻找新工作(我在 Google 很高兴),但让我很感兴趣的是,有这么多人在同一个问题上苦苦挣扎隐藏在一些复杂的装饰品后面。

一个示例模拟问题是这样说的:

想象一下你有图像,你可以复制任何你想要的图像,创建另一个图像。也可以复制新图像(副本),依此类推。新镜像虽然看起来一样,但名称不同,也可以追溯到父镜像。

现在,我们要删除所有图像,但如果图像有重复,我们无法删除它。您必须实现一个函数,该函数返回可以删除图像的顺序。

要实现的函数如下(我们在这篇文章中的所有代码都使用 Go):

func deleteOrder(imgs []*Image, cps []*CPOps) []*Image {...}

type Image struct {
  Name string
}// CPOps represent a copy operation. 
type CPOps struct {
  ParentImage *Image //Original images being copied. 
  CpImages []*Image  //Copies of the original image.
}

该函数接收图像列表,以及它们之间的复制操作,然后它必须返回我们必须遵循的顺序以根据上述规则删除所有图像。

让我们看一个例子:

Images = [A, B, C, D]
CPOps = [
  {ParentImage:A, CPImages:[B, C]},
  {ParentImage:B, CPImages:[D]},
]

这就是说A是原始图像,我们制作了两个副本,B和C。然后我们将B复制到D中。我们的函数的outdeleteOrder应该是[D,B,C,A]或[D, C、B、A] 或 [C、D、B、A]。请注意,可能有多种解决方案,但所有解决方案都是这样,每个图像只有在其副本被删除后才会被删除。

解决问题。

这个问题是一个经典的拓扑排序算法,其中建立了对象之间的某种依赖关系。向模拟面试的候选人提出了具有不同措辞的相同问题,但在所有情况下,问题都可以简化为拓扑排序。

我们在这篇文章中提出的解决方案是这样编写的,以便可以独立解释每个部分。但是,为了时间的缘故,在面试中编写可读性较差的代码是可以接受的。

构建图表

我希望到现在为止,读者可以意识到这是一个图形问题,这反过来应该是向面试官发出的第一个信号,即候选人了解正在发生的事情。

如果我们使用上面的示例构建图形,我们应该得到如下内容:

A --> B --> D
 \  
  --> C

现在,让我们创建一个给定输入的函数,我们可以构建一个可用于解决问题的图形。

type Graph map[string][]string

func buildGraph(imgs []*Image, copos []*CPOps) Graph {
	graph := make(Graph)

	// Add all images to the graph.
	for _, img := range imgs {
		if _, ok := graph[img.Name]; !ok {
			graph[img.Name] = []string{}
		}
	}

	// Add dependencies between images.
	for _, cp := range cpops {
		if _, ok := graph[cp.ParentImage.Name]; !ok {
			graph[cp.ParentImage.Name] = []string{}
		}
		for _, child := range cp.CPImages {
			graph[cp.ParentImage.Name] = append(graph[cp.ParentImage.Name], child.Name)
		}
	}

	return graph
}

构建图表

请注意,我们首先将所有节点(图像)添加到图中,这很重要,因为可能存在从未复制过的图像,因此它们永远不会处于给定的关系中。然后,我们建立节点之间的依赖关系。

现在,我们可以实现算法的主要部分,拓扑排序。

拓扑排序

拓扑排序是一个简单的 DFS,它使用依赖项作为有向边遍历图并返回相反的顺序。在我们的例子中,我们对依赖的相反顺序感兴趣,因为 A -> B,我们需要先删除 B,然后是 A。

func dfs(n string, graph Graph, visited map[string]bool, path []string) []string {
	for _, child := range graph[n] {
		if _, ok := visited[child]; ok {
			continue
		}
		visited[child] = true
		path = dfs(child, graph, visited, path)
	}
	return append(path, n)
}

DFS 在给定初始节点的情况下遍历图。

DFS 在给定初始节点的情况下遍历图,并以相反的顺序返回依赖关系。visited变量跟踪我们在图中已经访问过的节点(不再重复它们),变量跟踪path反向依赖关系。

现在我们有了构建图并遍历它的方法,我们必须立即将所有内容放在一起。

// DeletionOrder returns the order the images should be deleted. 
func DeletionOrder((imgs []*Image, cps []*CPOps) []*Image {
	graph := buildGraph(imgs, cps)

	visited := map[string]bool{}
	result := []string{}
	for k := range graph {
		if _, ok := visited[k]; !ok {
			visited[k] = true
			result = dfs(k, graph, visited, result)
		}
	}

	imgsMap := map[string]*Image{}
	for _, img := range imgs {
		imgsMap[img.Name] = img
	}
	imgsOrder := []*Image{}
	for _, name := range result {
		imgsOrder = append(imgsOrder, imgsMap[name])
	}
	return imgsOrder
}

DeletionOrder函数使用给定的输入构建图形,对于尚未访问的每个节点都将dfs执行。该result变量将以正确的删除顺序包含图像名称。

DeleteOrder函数的其余部分(第 14 行及以后)只是确保我们从图像名称中选择图像(在图形算法之外)。

 

大部分算法看起来并不复杂,但很多人都无法解决这个问题,我认为这在 45 分钟的采访中是可行的。我的观察是,大多数人未能足够快地识别该图形问题,从而有时间实施可行的解决方案。

其他注意事项

取决于面试官希望如何看待相同的问题,可以从不同的方向进行处理。

例如,当图有数千个节点时,放大算法的问题是一个有趣的问题。尽管它们可能看起来很简单,但需要考虑一些棘手的情况。

检测给定输入是否正确的问题也可能是一个有趣的问题。为了使图形可排序,从而使拓扑排序正常工作,图形必须没有循环。检测周期并不是一个特别复杂的问题,但大规模进行可能会有点问题。

这些都是有趣的问题,读者应该花点时间思考它们以及每个问题的含义。

最后,在 45 分钟的面试中,只有在正确编码主要问题后,才有时间解决其中的几个问号。但是,我们希望在这篇文章之后,读者可以看到一些问题,并轻松地将它们简化为可以使用拓扑排序解决的问题的图形类别。

 

祝面试顺利。

来源:https ://itnext.io/solving-a-graph-problem-with-go-f1049de33856

#go #graph 

用 Go 解决图问题

Resolvendo Um Problema De Gráfico Com Go

Neste tutorial, aprenderemos como resolver um problema de gráfico com Go. 

Nos últimos dias, tenho assistido a entrevistas de simulação ao vivo e, embora não esteja no mercado para um novo emprego (estou muito feliz no Google), é interessante para mim que tantas pessoas lutam com o mesmo problema escondido atrás de alguns adornos complicados.

Uma das perguntas simuladas de exemplo dizia algo assim:

Imagine que você tem imagens e pode duplicar qualquer imagem que desejar, criando outra imagem. A nova imagem (a duplicata) também pode ser copiada e assim por diante. Embora a nova imagem pareça a mesma, o nome é diferente e você também pode rastreá-la até a imagem pai.

Agora, queremos excluir todas as imagens, mas não podemos excluir uma imagem se ela tiver duplicatas. Você deve implementar uma função que retorne a ordem em que as imagens podem ser excluídas.

A função a ser implementada é a seguinte (estamos usando Go para todo o código neste post):

func deleteOrder(imgs []*Image, cps []*CPOps) []*Image {...}

type Image struct {
  Name string
}// CPOps represent a copy operation. 
type CPOps struct {
  ParentImage *Image //Original images being copied. 
  CpImages []*Image  //Copies of the original image.
}

A função recebe uma lista de imagens, e as operações de cópia entre elas, então ela deve retornar a ordem que devemos seguir para deletar todas as imagens com base na regra acima.

Vejamos um exemplo:

Images = [A, B, C, D]
CPOps = [
  {ParentImage:A, CPImages:[B, C]},
  {ParentImage:B, CPImages:[D]},
]

Isso está dizendo que A era a imagem original, e fizemos duas cópias, B e C. Então fizemos uma cópia de B em D. A saída de nossa função deleteOrderdeve ser [D, B, C, A] ou [D, C, B, A] ou [C, D, B, A]. Observe que várias soluções são possíveis, mas todas elas são tais que cada imagem é excluída somente depois que suas cópias são excluídas.

Resolvendo o problema.

Este problema é um algoritmo clássico de Classificação Topológica onde algum tipo de dependência entre objetos é estabelecido. O mesmo problema com um fraseado diferente foi apresentado aos candidatos das entrevistas simuladas, mas em todos os casos, o problema pôde ser reduzido a uma Classificação Topológica.

A solução que apresentamos neste post foi escrita para que cada peça possa ser explicada de forma independente. No entanto, em uma entrevista é aceitável escrever um código menos legível por uma questão de tempo.

Construindo o gráfico

Espero que a esta altura, o leitor possa perceber que se trata de um problema de grafo, que por sua vez deve ser o primeiro sinal para o entrevistador de que o candidato entende o que está acontecendo.

Se construirmos o gráfico usando o exemplo acima, devemos obter algo como:

A --> B --> D
 \  
  --> C

Agora, vamos criar uma função que dada a entrada, podemos construir um gráfico que pode ser usado para resolver o problema.

type Graph map[string][]string

func buildGraph(imgs []*Image, copos []*CPOps) Graph {
	graph := make(Graph)

	// Add all images to the graph.
	for _, img := range imgs {
		if _, ok := graph[img.Name]; !ok {
			graph[img.Name] = []string{}
		}
	}

	// Add dependencies between images.
	for _, cp := range cpops {
		if _, ok := graph[cp.ParentImage.Name]; !ok {
			graph[cp.ParentImage.Name] = []string{}
		}
		for _, child := range cp.CPImages {
			graph[cp.ParentImage.Name] = append(graph[cp.ParentImage.Name], child.Name)
		}
	}

	return graph
}

Construindo o gráfico

Observe que estamos adicionando todos os nós (imagens) ao gráfico primeiro, isso é importante, pois pode haver imagens que nunca foram copiadas, portanto, elas nunca estarão nas relações dadas. Em seguida, estabelecemos as dependências entre os nós.

Agora, podemos implementar a parte principal do algoritmo, o Topological Sort.

Classificação topológica

A ordenação topológica é um DFS simples que percorre o grafo usando as dependências como arestas direcionadas e retorna a ordem inversa. No nosso caso, estamos interessados ​​na ordem inversa das dependências, pois A — > B, precisamos excluir B primeiro, depois A.

func dfs(n string, graph Graph, visited map[string]bool, path []string) []string {
	for _, child := range graph[n] {
		if _, ok := visited[child]; ok {
			continue
		}
		visited[child] = true
		path = dfs(child, graph, visited, path)
	}
	return append(path, n)
}

DFS para percorrer o gráfico dado um nó inicial.

O DFS percorre o gráfico dado um nó inicial e retorna as dependências em ordem inversa. A visitedvariável acompanha os nós que já visitamos no gráfico (para não repeti-los), e a variável pathacompanha as dependências invertidas.

Agora que temos uma maneira de construir o gráfico e percorrê-lo, devemos juntar tudo de uma vez.

// DeletionOrder returns the order the images should be deleted. 
func DeletionOrder((imgs []*Image, cps []*CPOps) []*Image {
	graph := buildGraph(imgs, cps)

	visited := map[string]bool{}
	result := []string{}
	for k := range graph {
		if _, ok := visited[k]; !ok {
			visited[k] = true
			result = dfs(k, graph, visited, result)
		}
	}

	imgsMap := map[string]*Image{}
	for _, img := range imgs {
		imgsMap[img.Name] = img
	}
	imgsOrder := []*Image{}
	for _, name := range result {
		imgsOrder = append(imgsOrder, imgsMap[name])
	}
	return imgsOrder
}

A DeletionOrderfunção constrói o gráfico com a entrada dada, para cada nó que não foi visitado dfsé executado. A resultvariável conterá os nomes das imagens na ordem de exclusão correta.

O resto da DeleteOrderfunção (linha 14 em diante) é apenas certificar-se de que selecionamos as imagens dos nomes das imagens (fora do algoritmo do gráfico).

 

A maior parte do algoritmo não parece tão complexa e, no entanto, muitas pessoas não conseguem resolver esse problema, o que, na minha opinião, é factível em uma entrevista de 45 minutos. Minha observação é que a maioria das pessoas não consegue identificar esse problema gráfico com rapidez suficiente para ter tempo de implementar uma solução funcional.

outras considerações

O mesmo problema pode ser levado em direções diferentes, dependendo de como o entrevistador quer enxergá-lo.

Por exemplo, a questão de escalar o algoritmo, quando o gráfico tem milhares de nós, é interessante. Embora possam parecer simples, existem alguns casos complicados a serem considerados.

O problema de detectar se a entrada fornecida está correta também pode ser interessante. Para que o grafo seja classificável e, portanto, a ordenação topológica funcione corretamente, o grafo não deve ter ciclos. Detectar ciclos não é um problema particularmente complexo, mas fazê-lo em escala pode ser um pouco mais problemático.

Estas são questões interessantes e o leitor deve ter um momento para pensar sobre elas e as implicações de cada uma.

No final, em uma entrevista de 45 minutos, só há tempo disponível para resolver alguns desses pontos de interrogação somente após o problema principal ter sido codificado corretamente. No entanto, esperamos que após este post, o leitor possa olhar para alguns problemas e facilmente reduzi-los a esta categoria de gráficos de problemas solucionáveis ​​usando ordenação topológica.

 

Boa sorte na entrevista.

Fonte: https://itnext.io/solving-a-graph-problem-with-go-f1049de33856

#go #graph 

Resolvendo Um Problema De Gráfico Com Go
山岸  英樹

山岸 英樹

1656689905

Goでグラフ問題を解く

このチュートリアルでは、Goを使用してグラフの問題を解決する方法を学習します。 

ここ数日、私はライブのあざけりの面接を見てきました。新しい仕事を求めていないのに(Googleでとても満足しています)、多くの人が同じ問題に苦しんでいるのは興味深い結果です。いくつかの複雑な装飾品の後ろに隠されています。

模擬質問の例の1つは、次のようなものです。

画像があり、任意の画像を複製して別の画像を作成できると想像してください。新しいイメージ(複製)もコピーできます。新しい画像は同じように見えますが、名前が異なり、親画像までさかのぼることもできます。

ここで、すべての画像を削除したいのですが、重複している画像を削除することはできません。画像を削除できる順序を返す関数を実装する必要があります。

実装する関数は次のとおりです(この投稿のすべてのコードにGoを使用しています)。

func deleteOrder(imgs []*Image, cps []*CPOps) []*Image {...}

type Image struct {
  Name string
}// CPOps represent a copy operation. 
type CPOps struct {
  ParentImage *Image //Original images being copied. 
  CpImages []*Image  //Copies of the original image.
}

この関数は、画像のリストとそれらの間のコピー操作を受け取り、上記のルールに基づいてすべての画像を削除するために従う必要のある順序を返す必要があります。

一例を見てみましょう:

Images = [A, B, C, D]
CPOps = [
  {ParentImage:A, CPImages:[B, C]},
  {ParentImage:B, CPImages:[D]},
]

これは、Aが元の画像であり、BとCの2つのコピーを作成したことを意味します。次に、BのコピーをDに作成しました。関数の外はdeleteOrder[D、B、C、A]または[D、 C、B、A]または[C、D、B、A]。複数の解決策が可能であることに注意してください。ただし、それらはすべて、コピーが削除された後にのみすべての画像が削除されるようになっています。

問題の解決。

この問題は、オブジェクト間のある種の依存関係が確立される古典的なトポロジカルソートアルゴリズムです。模擬面接の候補者には、言い回しが異なる同じ問題が提示されましたが、すべての場合において、問題はトポロジカルソートに還元される可能性があります。

この投稿で紹介するソリューションは、各部分を個別に説明できるように書かれています。ただし、面接では、時間の都合上、読みにくいコードを書くことは許容されます。

グラフの作成

これまでに、読者がこれがグラフの問題であることに気付くことができることを願っています。これは、候補者が何が起こっているのかを理解しているという面接官への最初のシグナルになるはずです。

上記のサンプルを使用してグラフを作成すると、次のようになります。

A --> B --> D
 \  
  --> C

次に、入力を指定して、問題を解決するために使用できるグラフを作成できる関数を作成しましょう。

type Graph map[string][]string

func buildGraph(imgs []*Image, copos []*CPOps) Graph {
	graph := make(Graph)

	// Add all images to the graph.
	for _, img := range imgs {
		if _, ok := graph[img.Name]; !ok {
			graph[img.Name] = []string{}
		}
	}

	// Add dependencies between images.
	for _, cp := range cpops {
		if _, ok := graph[cp.ParentImage.Name]; !ok {
			graph[cp.ParentImage.Name] = []string{}
		}
		for _, child := range cp.CPImages {
			graph[cp.ParentImage.Name] = append(graph[cp.ParentImage.Name], child.Name)
		}
	}

	return graph
}

グラフの作成

最初にすべてのノード(画像)をグラフに追加していることに注意してください。これは、コピーされたことがない画像が存在する可能性があるため重要です。したがって、それらは特定の関係に含まれることはありません。次に、ノード間の依存関係を確立します。

これで、アルゴリズムの主要部分であるトポロジカルソートを実装できます。

トポロジカルソート

トポロジカルソートは、依存関係を有向エッジとして使用してグラフをトラバースし、逆の順序を返す単純なDFSです。この例では、A —> Bであるため、依存関係の順序を逆にすることに関心があります。最初にBを削除し、次にAを削除する必要があります。

func dfs(n string, graph Graph, visited map[string]bool, path []string) []string {
	for _, child := range graph[n] {
		if _, ok := visited[child]; ok {
			continue
		}
		visited[child] = true
		path = dfs(child, graph, visited, path)
	}
	return append(path, n)
}

初期ノードを指定してグラフをトラバースするDFS。

DFSは、初期ノードを指定してグラフをトラバースし、依存関係を逆の順序で返します。visited変数は、グラフですでにアクセスしたノードを追跡し(それらを繰り返さないようにするため)、変数はpath逆の依存関係を追跡します。

グラフを作成してトラバースする方法ができたので、すべてを一度にまとめる必要があります。

// DeletionOrder returns the order the images should be deleted. 
func DeletionOrder((imgs []*Image, cps []*CPOps) []*Image {
	graph := buildGraph(imgs, cps)

	visited := map[string]bool{}
	result := []string{}
	for k := range graph {
		if _, ok := visited[k]; !ok {
			visited[k] = true
			result = dfs(k, graph, visited, result)
		}
	}

	imgsMap := map[string]*Image{}
	for _, img := range imgs {
		imgsMap[img.Name] = img
	}
	imgsOrder := []*Image{}
	for _, name := range result {
		imgsOrder = append(imgsOrder, imgsMap[name])
	}
	return imgsOrder
}

このDeletionOrder関数は、指定された入力を使用してグラフを作成します。アクセスされていないノードごとに、dfsが実行されます。result変数には、正しい削除順序で画像名が含まれます。

関数の残りの部分DeleteOrder(14行目以降)は、(グラフアルゴリズムの外で)画像名から画像を選択していることを確認するだけです。

 

アルゴリズムの大部分はそれほど複雑に見えませんが、それでも非常に多くの人々がこの問題を解決できません。これは私の意見では45分のインタビューで実行可能です。私の観察では、ほとんどの人は、実用的なソリューションを実装する時間が十分にあるほど迅速にそのグラフの問題を特定できません。

その他の考慮事項

同じ問題は、インタビュアーがそれをどのように見たいかによって、異なる方向に進む可能性があります。

たとえば、グラフに数千のノードがある場合にアルゴリズムをスケールアップするという問題は興味深いものです。単純に見えるかもしれませんが、考慮すべきトリッキーなケースがいくつかあります。

与えられた入力が正しいかどうかを検出する問題も興味深いものになる可能性があります。グラフをソート可能にするため、つまりトポロジカルソートが正しく機能するためには、グラフにサイクルが含まれていてはなりません。サイクルの検出は特に複雑な問題ではありませんが、大規模に検出することは少し問題になる可能性があります。

これらは興味深い質問であり、読者はそれらとそれぞれの意味について考える時間をとる必要があります。

結局、45分間のインタビューでは、主な問題が正しくコーディングされて初めて、これらの疑問符のいくつかを解決するための時間しかありません。ただし、この投稿の後、読者がいくつかの問題を調べて、トポロジソートを使用して解決可能な問題のこのグラフカテゴリに簡単にまとめることができることを願っています。

 

幸運のインタビュー。

ソース:https ://itnext.io/solving-a-graph-problem-with-go-f1049de33856

#go #graph 

Goでグラフ問題を解く
Thierry  Perret

Thierry Perret

1656686160

Résoudre Un Problème De Graphe Avec Go

Dans ce tutoriel, nous allons apprendre à résoudre un problème de graphe avec Go. 

Au cours des deux derniers jours, j'ai regardé des interviews moqueuses en direct et même si je ne suis pas à la recherche d'un nouvel emploi (je suis très heureux chez Google), il est intéressant pour moi que tant de personnes luttent avec le même problème caché derrière des ornements compliqués.

L'un des exemples de questions fictives disait quelque chose comme ceci :

Imaginez que vous avez des images et que vous pouvez dupliquer n'importe quelle image que vous voulez, en créant une autre image. La nouvelle image (le doublon) peut également être copiée, et ainsi de suite. Bien que la nouvelle image ait la même apparence, le nom est différent et vous pouvez également la retracer jusqu'à l'image parente.

Maintenant, nous voulons supprimer toutes les images, mais nous ne pouvons pas supprimer une image si elle a des doublons. Vous devez implémenter une fonction qui renvoie l'ordre dans lequel les images peuvent être supprimées.

La fonction à implémenter est la suivante (nous utilisons Go pour tout le code dans ce post) :

func deleteOrder(imgs []*Image, cps []*CPOps) []*Image {...}

type Image struct {
  Name string
}// CPOps represent a copy operation. 
type CPOps struct {
  ParentImage *Image //Original images being copied. 
  CpImages []*Image  //Copies of the original image.
}

La fonction reçoit une liste d'images, et les opérations de copie entre elles, puis elle doit renvoyer l'ordre que nous devons suivre pour supprimer toutes les images en fonction de la règle ci-dessus.

Prenons un exemple :

Images = [A, B, C, D]
CPOps = [
  {ParentImage:A, CPImages:[B, C]},
  {ParentImage:B, CPImages:[D]},
]

Cela signifie que A était l'image originale, et nous avons fait deux copies, B et C. Ensuite, nous avons fait une copie de B dans D. La sortie de notre fonction deleteOrderdevrait être [D, B, C, A] ou [D, C, B, A] ou [C, D, B, A]. Notez que plusieurs solutions sont possibles, mais toutes sont telles que chaque image n'est supprimée qu'après la suppression de ses copies.

Résoudre le problème.

Ce problème est un algorithme de tri topologique classique où une sorte de dépendances entre les objets est établie. Le même problème avec une formulation différente a été présenté aux candidats des entretiens fictifs, mais dans tous les cas, le problème a pu être réduit à un Tri Topologique.

La solution que nous présentons dans cet article est écrite de manière à ce que chaque pièce puisse être expliquée indépendamment. Cependant, dans une interview, il est acceptable d'écrire un code moins lisible pour des raisons de temps.

Construire le graphique

J'espère que maintenant, le lecteur peut se rendre compte qu'il s'agit d'un problème de graphique, qui à son tour devrait être le premier signal à l'intervieweur que le candidat comprend ce qui se passe.

Si nous construisons le graphique en utilisant l'exemple ci-dessus, nous devrions obtenir quelque chose comme :

A --> B --> D
 \  
  --> C

Maintenant, créons une fonction qui, compte tenu de l'entrée, nous pouvons construire un graphique qui peut être utilisé pour résoudre le problème.

type Graph map[string][]string

func buildGraph(imgs []*Image, copos []*CPOps) Graph {
	graph := make(Graph)

	// Add all images to the graph.
	for _, img := range imgs {
		if _, ok := graph[img.Name]; !ok {
			graph[img.Name] = []string{}
		}
	}

	// Add dependencies between images.
	for _, cp := range cpops {
		if _, ok := graph[cp.ParentImage.Name]; !ok {
			graph[cp.ParentImage.Name] = []string{}
		}
		for _, child := range cp.CPImages {
			graph[cp.ParentImage.Name] = append(graph[cp.ParentImage.Name], child.Name)
		}
	}

	return graph
}

Construire le graphique

Notez que nous ajoutons d'abord tous les nœuds (images) au graphique, c'est important car il peut y avoir des images qui n'ont jamais été copiées, par conséquent, elles ne seront jamais dans les relations données. Ensuite, nous établissons les dépendances entre les nœuds.

Maintenant, nous pouvons implémenter la partie principale de l'algorithme, le tri topologique.

Tri topologique

Le tri topologique est un simple DFS qui parcourt le graphe en utilisant les dépendances comme arêtes dirigées et renvoie l'ordre inverse. Dans notre cas, nous nous intéressons à l'ordre inverse des dépendances puisque A — > B, nous devons d'abord supprimer B, puis A.

func dfs(n string, graph Graph, visited map[string]bool, path []string) []string {
	for _, child := range graph[n] {
		if _, ok := visited[child]; ok {
			continue
		}
		visited[child] = true
		path = dfs(child, graph, visited, path)
	}
	return append(path, n)
}

DFS pour parcourir le graphe étant donné un nœud initial.

Le DFS parcourt le graphe à partir d'un nœud initial et renvoie les dépendances dans l'ordre inverse. La visitedvariable garde la trace des nœuds que nous avons déjà visités dans le graphe (pour ne pas les répéter), et la variable pathgarde la trace des dépendances inversées.

Maintenant que nous avons un moyen de construire le graphe et de le parcourir, nous devons tout assembler en même temps.

// DeletionOrder returns the order the images should be deleted. 
func DeletionOrder((imgs []*Image, cps []*CPOps) []*Image {
	graph := buildGraph(imgs, cps)

	visited := map[string]bool{}
	result := []string{}
	for k := range graph {
		if _, ok := visited[k]; !ok {
			visited[k] = true
			result = dfs(k, graph, visited, result)
		}
	}

	imgsMap := map[string]*Image{}
	for _, img := range imgs {
		imgsMap[img.Name] = img
	}
	imgsOrder := []*Image{}
	for _, name := range result {
		imgsOrder = append(imgsOrder, imgsMap[name])
	}
	return imgsOrder
}

La DeletionOrderfonction construit le graphique avec l'entrée donnée, pour chaque nœud qui n'a pas été visité, il dfsest exécuté. La resultvariable contiendra les noms d'image dans l'ordre de suppression correct.

Le reste de la DeleteOrderfonction (ligne 14 et suivantes) s'assure simplement que nous sélectionnons les images à partir des noms d'images (en dehors de l'algorithme du graphe).

 

La majeure partie de l'algorithme n'a pas l'air si complexe, et pourtant tant de gens ne parviennent pas à résoudre ce problème, ce qui, à mon avis, est faisable en 45 minutes d'entretien. Mon observation est que la plupart des gens ne parviennent pas à identifier ce problème de graphe assez rapidement pour avoir le temps de mettre en œuvre une solution de travail.

autres considérations

Le même problème peut être pris dans des directions différentes selon la façon dont l'intervieweur veut le regarder.

Par exemple, la question de la mise à l'échelle de l'algorithme, lorsque le graphe a des milliers de nœuds, est intéressante. Bien qu'ils puissent sembler simples, certains cas délicats doivent être pris en compte.

Le problème de la détection si l'entrée donnée est correcte pourrait également être intéressant. Pour que le graphe soit triable, donc le tri topologique fonctionne correctement, le graphe ne doit pas avoir de cycles. La détection des cycles n'est pas un problème particulièrement complexe, mais le faire à grande échelle pourrait être un peu plus problématique.

Ce sont des questions intéressantes et le lecteur devrait prendre un moment pour y réfléchir et les implications de chacune.

Au final, dans un entretien de 45 minutes, il n'y a de temps disponible pour résoudre quelques-uns de ces points d'interrogation qu'après que le problème principal a été codé correctement. Cependant, nous espérons qu'après cet article, le lecteur pourra examiner certains problèmes et les réduire facilement dans cette catégorie graphique de problèmes résolubles à l'aide du tri topologique.

 

Bonne chance pour l'entretien.

Source : https://itnext.io/solver-a-graph-problem-with-go-f1049de33856

#go #graph 

Résoudre Un Problème De Graphe Avec Go
Go Programming

Go Programming

1656664449

Fuzz Testing (Fuzzing) | Write a Fuzz Test with Go (Golang)

How to write a fuzz test with Go (Golang) | Demo

Want to write a fuzz test? In this video, we are joined by Saba, a Software Engineering Manager at Google, who shows how to write a fuzz test for a simple reverse string function, run the go command, and understand the log. You will need Go 1.18 to write a fuzz test!

Go 1.18 installation instructions → https://goo.gle/3AbDsoA 

Chapters:
0:00 - Intro
0:19 - Prerequisites for Fuzzing
0:56 - Demo
6:16 - Wrap up

#go #golang #programming 

Fuzz Testing (Fuzzing) | Write a Fuzz Test with Go (Golang)
Bulah  Pfeffer

Bulah Pfeffer

1656658686

Twitch Clone with Flutter, Firebase, Agora & Go | Live Streaming App

Flutter Twitch Clone | Flutter Live Streaming App | Firebase | Agora

Build a Live Streaming App - Twitch Clone using Flutter, Firebase, Agora & Golang for Android, iOS, Web and MacOS.

Features:
- Email & Password Authentication
- Screensharing
- Selecting Thumbnail
- Going Live
- Joining LiveStream
- Switching Camera
- Muting/Unmuting
- Chatting
- Cross Platform
- Responsive UI
- Token Generation using GO (Create Your API)
- Deploy Server
- Deploy Website

Timestamps:
(00:00:00) Intro
(00:00:25) Demo
(00:04:45) Prerequisites
(00:05:00) ScreenSharing
(00:07:00) Project Layout
(00:16:48) Routes
(00:18:58) Onboarding Screen UI
(00:29:09) Signup & Login Screen UI
(00:40:33) Firebase Setup
(00:46:51) Firebase iOS Setup
(00:50:25) Firebase Android Setup
(00:54:06) Signing Up Users
(01:15:00) Logging in Users
(01:21:38) Persisting Login State
(01:29:25) Designing Bottom NavBar
(01:37:41) Go Live Screen UI
(01:51:27) Picking Image from Gallery
(02:03:01) Fixing Memory Leaks & Adding Loaders
(02:05:39) Storing Livestream Data in Firebase
(02:25:54) Agora Android Setup
(02:28:45) Solving Firebase Livestream BUG
(02:31:16) Agora iOS Setup
(02:33:16) Initialising Agora
(02:34:36) Get Agora App ID
(02:41:07) Joining Channel
(02:45:25) Generating Agora Temporary Token
(02:46:44) Designing Broadcast Screen
(02:52:51) Leaving Channel
(03:03:12) Switching Camera
(03:05:55) Muting/Unmuting
(03:07:21) Realtime Chatting
(03:22:13) Installing GO
(03:23:50) Creating & Deploying API using GO
(03:30:30) Sending HTTP Request to our API
(03:36:49) Designing & Displaying Feed Screen
(03:47:19) Correcting Join Channel Bug
(03:49:36) Firebase & Agora Web Setup
(03:53:38) Making The App Responsive
(04:04:02) Adding End Stream Button
(04:10:15) Start Screensharing Functionality
(04:15:13) Stop Screensharing Functionality
(04:19:10) Firebase & Agora MacOS Setup
(04:23:40) Conclusion
(04:24:24) Deploy Web App
(04:26:38) Conclusion Part 2

Source Code: https://github.com/RivaanRanawat/flutter-twitch-clone 
Go Server Code: https://github.com/RivaanRanawat/flutter-twitch-server 

Resources:
Agora Website: https://www.agora.io/ 
Go Lang Website: https://go.dev/dl/ 
FlutterFire CLI: https://firebase.flutter.dev/docs/cli 
Colors: https://github.com/RivaanRanawat/flutter-twitch-clone/blob/master/lib/utils/colors.dart 

#flutter #firebase #go #twitch #ui #golang 

Twitch Clone with Flutter, Firebase, Agora & Go | Live Streaming App

张 小龙

1656640547

How to Work With SQL Database In Golang (Fetch, Insert & Paginate Records)

In this latest Golang tutorial, we cover how to work with SQL database like Postgres in Go. The tutorial covers pagination, insertion and fetching of data from Postgres.

1. Connecting to Postgres SQL in Go
2. Running SQL migration from Go
3. Creating Records in Postgres 
4. Fetching Records
5. Paginating your records

Code: https://github.com/joefazee/working-with-sql-databases-go 

Subscribe: https://www.youtube.com/c/AbahJoseph/featured 

#go #golang 

How to Work With SQL Database In Golang (Fetch, Insert & Paginate Records)

张 小龙

1656640181

How to Send Emails using SMTP in Golang | Golang Tutorial

In this latest Golang tutorial, I explained how to send Emails using SMTP in Golang with two examples in Amazon SES & Mailtrap.

This can be good for those that want to learn how to setup Amazon SES in Go, and how to send bulk or transaction emails in Golang.

To clone the repository, click here https://github.com/joefazee/mailer 

Subscribe: https://www.youtube.com/c/AbahJoseph/featured 

#go #golang 

How to Send Emails using SMTP in Golang | Golang Tutorial
Code  Geek

Code Geek

1656639784

Build A Beautiful CLI Todo App in Golang | Golang Tutorial

We learned how to build a beautiful command line application in the Go programming language in this short screencast.

We cover essential topics like working with command line arguments in Go. How to pipe output of another program to your Go application.

Here are some important links

The full code is at https://github.com/joefazee/go-toto-app 
The ASCII Table Library is at https://github.com/alexeyco/simpletable 

Subscribe: https://www.youtube.com/c/AbahJoseph/featured 

#go #golang 
 

Build A Beautiful CLI Todo App in Golang | Golang Tutorial
Best of Crypto

Best of Crypto

1656500040

Go Binance API: Go Wrapper for Binance API

Binance API

To read full documentation, specs and find out which request params are required/optional, please visit the official documentation page.

Getting started

var logger log.Logger
logger = log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
logger = log.With(logger, "time", log.DefaultTimestampUTC, "caller", log.DefaultCaller)

hmacSigner := &binance.HmacSigner{
    Key: []byte("API secret"),
}
ctx, _ := context.WithCancel(context.Background())
// use second return value for cancelling request when shutting down the app

binanceService := binance.NewAPIService(
    "https://www.binance.com",
    "API key",
    hmacSigner,
    logger,
    ctx,
)
b := binance.NewBinance(binanceService)

Examples

Following provides list of main usages of library. See example package for testing application with more examples.

Each call has its own Request structure with data that can be provided. The library is not responsible for validating the input and if non-zero value is used, the param is sent to the API server.

In case of an standard error, instance of binance.Error is returned with additional info.

NewOrder

newOrder, err := b.NewOrder(binance.NewOrderRequest{
    Symbol:      "BNBETH",
    Quantity:    1,
    Price:       999,
    Side:        binance.SideSell,
    TimeInForce: binance.GTC,
    Type:        binance.TypeLimit,
    Timestamp:   time.Now(),
})
if err != nil {
    panic(err)
}
fmt.Println(newOrder)

CancelOrder

canceledOrder, err := b.CancelOrder(binance.CancelOrderRequest{
    Symbol:    "BNBETH",
    OrderID:   newOrder.OrderID,
    Timestamp: time.Now(),
})
if err != nil {
    panic(err)
}
fmt.Printf("%#v\n", canceledOrder)

Klines

kl, err := b.Klines(binance.KlinesRequest{
    Symbol:   "BNBETH",
    Interval: binance.Hour,
})
if err != nil {
    panic(err)
}
fmt.Printf("%#v\n", kl)

Trade Websocket

interrupt := make(chan os.Signal, 1)
signal.Notify(interrupt, os.Interrupt)

kech, done, err := b.TradeWebsocket(binance.TradeWebsocketRequest{
    Symbol: "ETHBTC",
})
if err != nil {
    panic(err)
}
go func() {
    for {
        select {
        case ke := <-kech:
            fmt.Printf("%#v\n", ke)
        case <-done:
            break
        }
    }
}()

fmt.Println("waiting for interrupt")
<-interrupt
fmt.Println("canceling context")
cancelCtx()
fmt.Println("waiting for signal")
<-done
fmt.Println("exit")
return

Known issues

  • Websocket error handling is not perfect and occasionally attempts to read from closed connection.

Download Details:
Author: binance-exchange
Source Code: https://github.com/binance-exchange/go-binance
License: MIT license

#Binance #blockchain #go #golang

Go Binance API: Go Wrapper for Binance API
Best of Crypto

Best of Crypto

1656124500

Conflux Golang API For Wallet

This is a SDK for developers who would like to port a wallet with Conflux network.

Conflux has provided conflux-go-sdk to support the operation of communicating with nodes, accounts manager and contract operation. The conflux-go-sdk-for-wallet is developed for the convenience of wallet development, there are some complex APIs are provided through communicate with centralized server. Currently, it is mainly for querying summary of user transactions and token transfer event.

The Conflux Golang API allows any Golang client to interact with a local or remote Conflux node based on JSON-RPC 2.0 protocol. With Conflux Golang API, user can easily manage accounts, send transactions, deploy smart contracts and query blockchain information.

Install

go get github.com/Conflux-Chain/go-conflux-sdk-for-wallet

You can also add the Conflux Golang API For Wallet into vendor folder.

govendor fetch github.com/Conflux-Chain/go-conflux-sdk-for-wallet

Usage

api document

Download Details:
Author: Conflux-Chain
Source Code: https://github.com/Conflux-Chain/go-conflux-sdk-for-wallet
License:

#Conflux #blockchain #smartcontract #go

Conflux Golang API For Wallet
Oral  Brekke

Oral Brekke

1656061260

Playwright-go: Playwright Port for Golang

🎭 Playwright for Go

Playwright is a Go library to automate Chromium, Firefox and WebKit with a single API. Playwright is built to enable cross-browser web automation that is ever-green, capable, reliable and fast.

 LinuxmacOSWindows
Chromium 101.0.4929.0
WebKit 15.4
Firefox 97.0.1

Headless execution is supported for all the browsers on all platforms.

Installation

go get github.com/playwright-community/playwright-go

Install the browsers and OS dependencies:

go run github.com/playwright-community/playwright-go/cmd/playwright install --with-deps
# Or
go install github.com/playwright-community/playwright-go/cmd/playwright
playwright install --with-deps

Alternatively you can do it inside your program via which downloads the driver and browsers:

err := playwright.Install()

Capabilities

Playwright is built to automate the broad and growing set of web browser capabilities used by Single Page Apps and Progressive Web Apps.

  • Scenarios that span multiple page, domains and iframes
  • Auto-wait for elements to be ready before executing actions (like click, fill)
  • Intercept network activity for stubbing and mocking network requests
  • Emulate mobile devices, geolocation, permissions
  • Support for web components via shadow-piercing selectors
  • Native input events for mouse and keyboard
  • Upload and download files

Example

The following example crawls the current top voted items from Hacker News.

package main

import (
    "fmt"
    "log"

    "github.com/playwright-community/playwright-go"
)

func main() {
    pw, err := playwright.Run()
    if err != nil {
        log.Fatalf("could not start playwright: %v", err)
    }
    browser, err := pw.Chromium.Launch()
    if err != nil {
        log.Fatalf("could not launch browser: %v", err)
    }
    page, err := browser.NewPage()
    if err != nil {
        log.Fatalf("could not create page: %v", err)
    }
    if _, err = page.Goto("https://news.ycombinator.com"); err != nil {
        log.Fatalf("could not goto: %v", err)
    }
    entries, err := page.QuerySelectorAll(".athing")
    if err != nil {
        log.Fatalf("could not get entries: %v", err)
    }
    for i, entry := range entries {
        titleElement, err := entry.QuerySelector("td.title > a")
        if err != nil {
            log.Fatalf("could not get title element: %v", err)
        }
        title, err := titleElement.TextContent()
        if err != nil {
            log.Fatalf("could not get text content: %v", err)
        }
        fmt.Printf("%d: %s\n", i+1, title)
    }
    if err = browser.Close(); err != nil {
        log.Fatalf("could not close browser: %v", err)
    }
    if err = pw.Stop(); err != nil {
        log.Fatalf("could not stop Playwright: %v", err)
    }
}

More examples

How does it work?

Playwright is a Node.js library which uses:

  • Chrome DevTools Protocol to communicate with Chromium
  • Patched Firefox to communicate with Firefox
  • Patched WebKit to communicate with WebKit

These patches are based on the original sources of the browsers and don't modify the browser behaviour so the browsers are basically the same (see here) as you see them in the wild. The support for different programming languages is based on exposing a RPC server in the Node.js land which can be used to allow other languages to use Playwright without implementing all the custom logic:

The bridge between Node.js and the other languages is basically a Node.js runtime combined with Playwright which gets shipped for each of these languages (around 50MB) and then communicates over stdio to send the relevant commands. This will also download the pre-compiled browsers.

Is Playwright for Go ready?

We are ready for your feedback, but we are still covering Playwright Go with the tests.

Resources

Looking for maintainers and see here. Thanks!       

API reference | Example recipes

Author: Playwright-community
Source Code: https://github.com/playwright-community/playwright-go 
License: MIT license

#node #playwright #go #golang 

Playwright-go: Playwright Port for Golang