Skip to content

Instantly share code, notes, and snippets.

@cauesmelo
Created October 14, 2022 20:29
Show Gist options
  • Save cauesmelo/91647a52fb2622b030824eed2c119ed8 to your computer and use it in GitHub Desktop.
Save cauesmelo/91647a52fb2622b030824eed2c119ed8 to your computer and use it in GitHub Desktop.
Desafio.go
package main
import (
"fmt"
"os"
"strconv"
)
func getInput() int {
if len(os.Args) <= 1 {
fmt.Print("Usage: go a.out <integer >= 1>")
os.Exit(-123)
}
arg := os.Args[1]
input, err := strconv.Atoi(arg)
if err != nil || input < 1 {
fmt.Printf("wrong input '%s'. Usage: go a.out <integer >= 1>", arg)
os.Exit(-124)
}
return input
}
// Funcão para calcular valores da semi diagonal
func calcValue(x int, y int, input int, upperValue int) int {
// Calculo o valor de cada salto com base na posição x
var jump = ((input - x) - 1) - (x)
// Somo o valor acima, e dou um salto para cada lado(esq, dir, cima, baixo)
// Por fim, tiramos um e chegamos ao valor na diagonal do upperValue
return upperValue + ((4 * jump) - 1)
}
// Método para impressão de linha
func printLine(line []int) {
fmt.Print("[")
for i := 0; i < len(line); i++ {
fmt.Print(line[i])
if i != len(line)-1 {
fmt.Print("\t")
}
}
fmt.Println("]")
}
// Método para preencher sequencialmente a partir de um valor e posição
func fillLine(line []int, startValue int, startPosX int, endPosX int) {
var currentValue = startValue
for i := startPosX; i <= endPosX; i++ {
line[i] = currentValue
currentValue++
}
}
// Método para preencher sequencialmente a partir de um valor e posição em ordem reversa
func fillLineReverse(line []int, startValue int, startPosX int, endPosX int) {
var currentValue = startValue
for i := startPosX; i >= endPosX; i-- {
line[i] = currentValue
currentValue++
}
}
// Função auxiliar para calcular o salto a direita
func getShiftRight(line int, input int) int {
if line > (input / 2) {
return input - line
}
return line
}
// Função auxiliar para calcular o salto a esquerda
func getShiftLeft(shiftRight int) int {
if shiftRight == 0 {
return 0
}
return shiftRight - 1
}
func main() {
// Recebe input
var input = getInput()
// Armazena linha anterior, utilizada para cálcular próxima linha
var previousLine = make([]int, input)
// Array para ir armazenando a linha atual
var currentLine = make([]int, input)
// Linha atual
var posY = 0
// Percorremos por todas as linhas possíveis
for posY != input {
// Se for a primeira linha, basta preenchermos com uma sequência simples a partir do 1
if posY == 0 {
fillLine(currentLine[:], 1, 0, input-1)
}
// Se não for a primeira linha
if posY != 0 {
// Calculo a quantidade de saltos à direita
var shiftRight = getShiftRight(posY, input)
// Calculo a quantidade de saltos a esquerda
var shiftLeft = getShiftLeft(shiftRight)
// Calculo da semi diagonal
var calculatedValue = calcValue(shiftLeft, posY, input, previousLine[shiftLeft])
// Se foi possível calcular, preenche a sequência
if calculatedValue <= input*input {
var startPosX = shiftLeft
var endPosX = input - 1 - shiftRight
fillLine(currentLine[:], calculatedValue, startPosX, endPosX)
}
// Preencho valores saltados a esquerda
for i := 0; i < shiftLeft; i++ {
currentLine[i] = previousLine[i] - 1
}
// Preencho valores saltados a direita
for i := input - 1; i >= input-shiftRight; i-- {
currentLine[i] = previousLine[i] + 1
}
// Se passamos da metade da matriz, já temos valores suficientes para preencher
if posY > input/2 {
var startPosX = input - shiftRight - 1
var endPosX = shiftLeft
var startValue = currentLine[input-shiftRight] + 1
fillLineReverse(currentLine[:], startValue, startPosX, endPosX)
}
}
// Por fim, imprimimos a linha atual
printLine(currentLine)
// Salvo essa linha na variável auxiliar
previousLine = currentLine
// Limpo a linha atual
currentLine = make([]int, input)
// Coloco apontador de linha na próxima posição
posY++
}
fmt.Println("")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment