text:
<repo_name>Ye-Yong-Chi/sligen<file_sep>/README.md
# sligen

An slide generator that makes you pitch like a boss.

## How to use

1. Register an [Pixaby](https://pixabay.com/en/) account
2. Configure your src/crawlers/config.py
3. Run `src/download_image.py`
4. Use `make` to generate your slide

## Dependency

- python 3
    - beautifulsoup4
    - requests
    - jieba
    - jinja2

## License

[MIT License](LICENSE)
<file_sep>/src/generate.py
import os
import sys
import random
from slidegen import Generator
from slidegen import DataProvider
from wordgen import Wordgen

if len(sys.argv) < 2:
    print('Usage: %s output-path' % sys.argv[0])
    exit(1)

class WordgenProvider(DataProvider):
    def __init__(self):
        self.wg = Wordgen()

    def text(self):
        return self.wg.moistPhrase()

class GeneratorBridge(object):
    def __init__(self, generator, output_path):
        self.generator = generator
        self.path = output_path
        self.index = 0

    def __hook(self, val):
        self.index += 1
        with open(os.path.join(self.path, '%.3d.md' % self.index), 'w', encoding='utf-8') as fo:
            fo.write(val)
        return val

    def __getattr__(self, name):
        f = getattr(self.generator, name)
        def _proc(*args):
            return self.__hook(f(*args))
        return _proc

g = Generator(WordgenProvider())
g = GeneratorBridge(g, sys.argv[1])

g.cover()
for i in range(18):
    if random.randint(0, 100) < 83:
        g.content()
    else:
        g.full_image()
<file_sep>/index.php
<!DOCTYPE html>

    <meta charset="UTF-8">
    <title>Sligen Online Demo</title>

Generate slide and pitch like a boss!

Preview

    <?php
        error_reporting(0);
        if($_POST['generate']) {
            $pwd = dirname(__FILE__);
            system("cd {$pwd} && make 2>&1 >/dev/null");
            echo '
Enjoy your slide!
';
        }
    ?>
    <form action="." method="POST">
        <input type="hidden" name="generate" value="1">
        <input type="submit" value="re-generate">
    </form>

Source code is available here.

<file_sep>/main/makeslide.py
import jinja2
from jinja2.environment import Environment
import glob
import random

env = Environment()
env.loader = jinja2.FileSystemLoader('.')
tem = env.get_template('./template.html')
s_all = []

cht = []
for s in glob.glob('Chart.js/samples/*'):
    print(s)
    cht.append(s)

flist = glob.glob('slides/*.md')
flist.sort()
for f in flist:
    print(f)
    with open(f, encoding='utf-8') as fo:
        i = random.randint(0,3)
        if i > 0:
            s_all.append('
\n'+fo.read()+'\n
\n')
        else:
            r = random.choice(cht)
            s_all.append('
\n'+fo.read()+'\n
\n')

out = tem.render(slides = s_all)

index = open("output.html", "w", encoding='utf-8')
index.write(out)
<file_sep>/Makefile
all:
	python3 src/generate.py main/slides
	cd main && python3 makeslide.py

branch_name: refs/heads/master

languages: Makefile Markdown Python PHP

repo_language: Makefile

repo_name: Ye-Yong-Chi/sligen


text:
<repo_name>jakobib/zuganggestalten2017<file_sep>/slides.md
---
title: Anleitung für schlechte Standards
author: <NAME>, VZG
date: 19.10.2017 -- ZUGANG GESTALTEN!
...

# Those were the data my friend... {data-background=https://upload.wikimedia.org/wikipedia/commons/b/bc/Paul_Otlet_%C3%A0_son_bureau.jpg}

Zunächst ein Hinweis: ich habe nicht nur theoretisch sondern auch praktisch
viel mit Metadaten aus verschiedenen Quellen und in verschiedenen Formen zu
tun. Die Qualität dieser Daten lässt zuweilen etwas zu wünschen übrig. Die
folgenden Hinweise für schlechte Standards, also Anti-Patterns die eigentlich
vermieden werden sollten, basieren daher zu Größten Teil auf Beispielen aus der
Praxis.

# Ignoriere alle Regeln! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/6/64/Art_Anarchy.jpg/1200px-Art_Anarchy.jpg}

Die erste Regel lautet alle Regel zu ignorieren. Wenn alle ihre Daten so
gestalten und interpretieren wie es ihnen gerade in den Sinn kommt, muss sich
niemand an Standards halten. Das mag übertrieben erscheinen, aber in der Praxis
bekommen wir beispielsweise regelmäßig irgendwelche Excel-Tabellen und müssen
selbst daraus schlau werden.

# Lass' es bei ungeschriebenen Gesetzen! {data-background=https://upload.wikimedia.org/wikipedia/commons/9/96/FMRI_Brain_Scan.jpg}

Das Sache ist aber so dass Daten *immer* irgendwelchen Regeln folgend. Die
Regeln sind nur meist nirgends festgelegt sondern lassen sich beispielsweise
als haben-wir-schon-immer-so-gemacht zusammenfassen. Belassen Sie es als für
schlechte Standards bei implizite Annahmen.

# Halte deine Regeln geheim! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/3/35/Locked_Door_of_Tajjar.jpg/1200px-Locked_Door_of_Tajjar.jpg}

Wenn es sich doch nicht vermeiden lässt irgendwelche Standards festzulegen,
behalte sie für den internen Gebrauch. Daten austauschen ist ja ok aber die
Regeln denen die Standard gehorchen sollten geheim bleiben.

# Standards sollten unzugänglich sein! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Warning_-_Area_Closed_-_Dangerous_Cliffs.jpg/1200px-Warning_-_Area_Closed_-_Dangerous_Cliffs.jpg}

Stell' sicher, dass deine Regeln möglichst schwer einsehbar sind, also nicht frei zugänglich.
Ein aktuelles Beispiel ist vor wenigen Tagen entdeckte Sicherheitslücke im WLAN-Standard, die
daher rührt, dass der exakte Standard nicht kostenlos verfügbar war.

# Erfinde das Rad von Grund auf neu! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/b/b2/Broken_Wheel.jpg/1200px-Broken_Wheel.jpg}

Vielleicht gibt es ja schon einen Standard für Ihren Anwendungsfall. Erfinde
lieber das Rad neu und ignoriere ähnliche Standards. Gute Standards bauen aufeinander
auf, also sollten schlechte Standards jedes Details selbst regeln.

# Plane möglichst umfangreich! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Category-diagram.png/1200px-Category-diagram.png}

Also plane möglichst umfangreich. Ein schlechter Standard sollte die gesamte
Welt erklären und alle möglichen Spezialfälle abdecken. Am Besten sie
konzentrieren sich gleich auf die Spezial- und Sonderfälle!

# Beschränke dich aufs Allgemeine! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/3/39/Blank-document.svg/262px-Blank-document.svg.png data-background-size=contain}

Versuchen Sie jedoch nicht zu sehr ins Detail zu gehen. Ein allgemeiner
Standard reicht aus.  Lassen sie viele Freiheistgrade und Möglichkeiten offen,
so dass sie jeder sie auf seine eigene Weise unterschiedlich ausgestalten kann.
Schöne Beispiel sind das Dublin Core Metadata Element Set oder die DIN-A4-Norm:
an sich keine schlechten Standards aber für sich alleine meist nicht
ausreichend. Das Daten nach ihrer Form statt ihrem Inhalt standardisiert werden
ist übrigens eher die Regel.

# Jedem Einzelfall sein Standard {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/a/a6/Messier_12_Hubble_WikiSky.jpg/600px-Messier_12_Hubble_WikiSky.jpg}

Das Andere extrem sind eine Vielzahl von Standard für jeden Einzelfall.

# Vermeide gute Beispiele!

Hierfür ist mir auch kein gutes Beispiel als Hintergrundbild eingefallen. Am
Besten Sie lassen für schlechte Standards Beispiele ganz weg. Diese Regel ist
auch nicht schwer einzuhalten, da wirklich gute Beispiele tatsächlich aufwändig
sind.

# Benutze kryptische Sprache! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/6/67/Voynich_Manuscript_%28164%29.jpg/1200px-Voynich_Manuscript_%28164%29.jpg}

Zugegeben sind Standards oft nicht wirklich leicht und flüssig lesbar, da sie
viel mit Gesetzestexten und -Kommentaren gemeinsam haben. Es gibt aber immer
Spielraum nach oben, es unnötig noch unverständlicher zu machen.

# Bleibe unklar bezüglich relevanter Teile! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Salmonberry_River_and_POTB_line.jpg/800px-Salmonberry_River_and_POTB_line.jpg}

Jeder Datenstandard lässt einigen Spielraum, so dass die gleichen Inhalte
unterschiedlich kodiert werden können. Ein typisches Beispiel sind zusätzliche
Leerzeichen. Ein schlechter Standard sollte nicht preisgeben, wann solche
Abweichungen relevant sind und wann sie ignoriert werden können.

# Fördere kreative Lösungen! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/4/49/Princess_juliana_international_airport_approach.jpg/800px-Princess_juliana_international_airport_approach.jpg}

Jeder Standard lässt sich uminterpretieren und verbiegen. Ein schlechter
Standard sollte diese Praxis fördern. Ein Beispiel aus der Praxis über das ich
neulich gestolpert bin stammt aus bibliographischen Metadaten in denen ein Feld
für den Titel einer Publikation vorhanden war. Irgendwann fiel mir auf, dass
machen Titel komische Sonderzeichen enthalten. Die Lösung war folgender Hack:
Wenn der Titel nicht Englisch ist, dann steht im Titel-Feld nicht der
tatsächliche Titel sondern der übersetze Titel in eckigen Klammern. Darauf
muss man erstmal kommen!

# Vermeide formale Sprachen! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/8/8e/Thompson-kleene-star.svg/755px-Thompson-kleene-star.svg.png}

Allgemein sollte schon klar geworden sein, dass schlechte Standards sich nicht
zu sehr festlegen sollten. Das beste Mittel dafür ist ungenaue Sprache. Das
Gegenteil davon sind formale Sprachen wie reguläre Ausdrücke, Schemata,
Datentypen, Ontologien etc. Diese Sprachen dienen der Exaktheit und helfen
Computern besser mit den Daten umzugehen. Sie erfordern allerdings
mathematische Stringenz.

# Bleibe abstrakt! {data-background=https://upload.wikimedia.org/wikipedia/commons/6/62/Larry.jpg data-background-size=contain}

Andererseits ist es auch möglich, sich nur auf formale Sprachen und Systeme zu
beschränken.  Bleibe also besser möglichst abstrakt, ohne Bezug zu konkreten
Umsetzungen. Die konkreten Anwendungsfälle wird dann jeder anders umsetzen. Es
ist nämlich so, dass formale Sprachen alleine zwar exakt sind aber keinen Bezug
zur Realität haben, da es sich um rein mathematische Konstrukte handelt.

# Beschränke dich auf eine Technik! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/6/68/XML.svg/527px-XML.svg.png data-background-size=contain}

Datenstandards können zusammen mit verschiedenen Programmiersprachen,
Anwendungen und anderen Techniken eingesetzt werden. Pass daher auf, dass dein
Standard nicht Sprach-unabhängig ist und wohlmöglich mit verschiedenen
Techniken eingesetzt werden kann. Am besten der Standard bezieht sich nur auf
einen ganz bestimmten technischen Kontext.

# Ändere nichts! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/d/d9/Rocks_blocking_a_road.jpg/1200px-Rocks_blocking_a_road.jpg data-state=top}

Gute Standards stammen aus der Praxis. Die Praxis kann sich jedoch mit der Zeit
ändern.  Das sollte kein Grund sein, den Standard ebenfalls anzupassen. Also
lassen sie ihre Standards auf Ewigkeit so wie sie sind!

# Vermeide Versionierung! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/7/77/Ausgrabung_Harburger-Schlo%C3%9Fstra%C3%9Fe_Profil.jpg/1200px-Ausgrabung_Harburger-Schlo%C3%9Fstra%C3%9Fe_Profil.jpg}

Falls sie etwas am Standard ändern, machen sie es so, dass nicht erkennbar ist,
wann was geändert wurde und wie der Standard vor der Änderung aussah.

# Validiere nie! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/a/a0/Japanese_Three_Wise_Monkeys.JPG/1280px-Japanese_Three_Wise_Monkeys.JPG}

Standards sind Abmachungen, sie können also eingehalten oder gebrochen werden.
Am besten sie schauen gar nicht erst genau hin, ob sich überhaupt jemand an den
Standard hält oder nur so tut.

# Ignoriere Regelverstöße! {data-background=https://upload.wikimedia.org/wikipedia/commons/thumb/3/34/Massimo_Busacca%2C_Referee%2C_Switzerland_%2810%29.jpg/1280px-Massimo_Busacca%2C_Referee%2C_Switzerland_%2810%29.jpg}

Jeder Standard ist nur so gut wie er auch eingealten wird.  Wenn Regelverstöße
keine Konsequenzen nach sich ziehen (also zum Beispiel Fehlersuche, Rückmeldung,
Ablehnung von Daten...) wird sich am Ende sowieso niemand mehr daran halten.

# Ignoriere soziale Aspekte! {data-background=https://upload.wikimedia.org/wikipedia/commons/8/8f/This_was_a_timely_capture_%283926001309%29.jpg}

Kein Standard ist frei von Interessen. Ein gutes Rezept zum Scheitern ist es
daher so zu tun als seien Daten eine rein technische Angelegenheit ohne soziale
Implikationen und Konflikte.

# Bildlizenzen 1/3

-   [<NAME> à son
    bureau](https://commons.wikimedia.org/wiki/File:Paul_Otlet_%C3%A0_son_bureau.jpg),
    PD
-   [Eekiv](https://commons.wikimedia.org/wiki/User:Eekiv), [Art
    Anarchy](https://commons.wikimedia.org/wiki/File:Art_Anarchy.jpg),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [DrOONeil](https://commons.wikimedia.org/wiki/User:DrOONeil), [FMRI
    Brain
    Scan](https://commons.wikimedia.org/wiki/File:FMRI_Brain_Scan.jpg),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [Soban](https://commons.wikimedia.org/wiki/User:Soban), [Locked Door
    of
    Tajjar](https://commons.wikimedia.org/wiki/File:Locked_Door_of_Tajjar.jpg),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [Wing-Chi Poon](https://commons.wikimedia.org/wiki/User:Wingchi),
    [Warning - Area Closed - Dangerous
    Cliffs](https://commons.wikimedia.org/wiki/File:Warning_-_Area_Closed_-_Dangerous_Cliffs.jpg),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [Samooer](https://commons.wikimedia.org/wiki/User:Samooer), [Broken
    Wheel](https://commons.wikimedia.org/wiki/File:Broken_Wheel.jpg),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [Gurch](https://en.wikipedia.org/wiki/User:Gurch) at [English
    Wikipedia](https://en.wikipedia.org/wiki/),
    [Category-diagram](https://commons.wikimedia.org/wiki/File:Category-diagram.png),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)

# Bildlizenzen 2/3

-   [PdDemeter](https://commons.wikimedia.org/wiki/User:PdDemeter),
    [Blank-document](https://commons.wikimedia.org/wiki/File:Blank-document.svg),
    [CC BY-SA
    2.5](https://creativecommons.org/licenses/by-sa/2.5/legalcode)
-   [Messier 12 Hubble
    WikiSky](https://commons.wikimedia.org/wiki/File:Messier_12_Hubble_WikiSky.jpg),
    PD
-   [Voynich
    Manuscript (164)](https://commons.wikimedia.org/wiki/File:Voynich_Manuscript_%28164%29.jpg),
    PD
-   [<NAME>](http://www.flickr.com/people/cupdegrave/),
    [Salmonberry River and POTB
    line](https://commons.wikimedia.org/wiki/File:Salmonberry_River_and_POTB_line.jpg),
    [CC BY 2.0](https://creativecommons.org/licenses/by/2.0/legalcode)
-   [<NAME>](http://blog.fuzzynerd.com/), [Princess juliana
    international airport
    approach](https://commons.wikimedia.org/wiki/File:Princess_juliana_international_airport_approach.jpg),
    [CC BY 3.0](https://creativecommons.org/licenses/by/3.0/legalcode)
-   [Trapmoth](/wiki/User_talk:Trapmoth),
    [Thompson-kleene-star](https://commons.wikimedia.org/wiki/File:Thompson-kleene-star.svg),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [Larry](https://commons.wikimedia.org/wiki/File:Larry.jpg), PD

# Bildlizenzen 3/3

-   [en:User:Dreftymac](https://en.wikipedia.org/wiki/User:Dreftymac),
    [XML](https://commons.wikimedia.org/wiki/File:XML.svg), [CC BY-SA
    2.5](https://creativecommons.org/licenses/by-sa/2.5/legalcode)
-   אני יצרתי, [Rocks blocking a
    road](https://commons.wikimedia.org/wiki/File:Rocks_blocking_a_road.jpg),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [Bullenwächter](https://commons.wikimedia.org/wiki/User:Bullenw%C3%A4chter),
    [Ausgrabung Harburger-Schloßstraße
    Profil](https://commons.wikimedia.org/wiki/File:Ausgrabung_Harburger-Schloßstraße_Profil.jpg),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [Man On
    Mission](https://commons.wikimedia.org/wiki/User:Man_On_Mission),
    [Japanese Three Wise
    Monkeys](https://commons.wikimedia.org/wiki/File:Japanese_Three_Wise_Monkeys.JPG),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [Steindy](https://commons.wikimedia.org/wiki/User:Steindy), [Massimo
    Busacca, Referee,
    Switzerland (10)](https://commons.wikimedia.org/wiki/File:Massimo_Busacca,_Referee,_Switzerland_(10).jpg),
    [CC BY-SA
    3.0](https://creativecommons.org/licenses/by-sa/3.0/legalcode)
-   [<NAME>](http://www.flickr.com/people/68877611@N00) from
    San Francisco, USA, [This was a timely
    capture (3926001309)](https://commons.wikimedia.org/wiki/File:This_was_a_timely_capture_(3926001309).jpg),
    [CC BY-SA
    2.0](https://creativecommons.org/licenses/by-sa/2.0/legalcode)

<file_sep>/Makefile
# requires Pandoc::Elements

# add -V showNotes=true to include speaker notes

slides.html: slides.md
	pandoc -s -S -t revealjs -V revealjs-url=http://lab.hakim.se/reveal-js \
		-V theme=black -V transition=fade -V backgroundTransition=fade \
		--css style.css $< -o $@
<file_sep>/images.pl
#!/usr/bin/env perl
use v5.14;

use Pandoc;
use Pandoc::Elements;

my $doc = pandoc->file;
my $imgs = $doc->query('Header' => sub { $_->keyvals->{'data-background'} });

for (@$imgs) {
    s{^https?://upload\.wikimedia\.org/wikipedia/commons/}{} or next;
    s{^(thumb/)?./../([^/]+)(/.+)?$}{$2};
    say "https://commons.wikimedia.org/wiki/File:$_";
}

languages: Makefile Markdown Perl


text:
<repo_name>folivero/ReduxBlueprint<file_sep>/ReduxBlueprint/PresentationContainerComponent.swift
import Foundation

public final class PresentationContainerComponent<State, Action, Command, Properties> {
    private let container:  ContainerComponent<State, Action, Command, Properties>
    private let update: (Properties) -> Void

    public init(
        store: Store<State, Action>,
        mapStateToProperties: @escaping (State) -> Properties,
        mapCommandToAction: @escaping (Command) -> Action?,
        update: @escaping (Properties) -> Void)
    {
        self.update = update
        container = ContainerComponent(
            store: store,
            mapStateToProperties: mapStateToProperties,
            mapCommandToAction: mapCommandToAction
        )
        container.delegate = self
    }

    public func dispatch(command: Command) {
        container.dispatch(command: command)
    }
}

// MARK: ContainerComponentDelegate

extension PresentationContainerComponent: ContainerComponentDelegate {
    public func containerComponentChanged() {
        update(container.properties)
    }
}
<file_sep>/README.md
[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)

# ReduxBlueprint

A blueprint of a minimal version of Redux written in Swift, as depicted in the following figure

![Components](https://user-images.githubusercontent.com/5747808/33975326-d75b2ad2-e05b-11e7-9100-25b6a2181ac6.jpg)

More info on Redux at https://redux.js.org

...more details comming soon

<file_sep>/ReduxBlueprint/ReduxBlueprint.h
#import <Foundation/Foundation.h>

//! Project version number for ReduxBlueprint.
FOUNDATION_EXPORT double ReduxBlueprintVersionNumber;

//! Project version string for ReduxBlueprint.
FOUNDATION_EXPORT const unsigned char ReduxBlueprintVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <ReduxBlueprint/PublicHeader.h>

<file_sep>/ReduxBlueprint/ContainerComponent.swift
import Foundation

// Container components: Are concerned with how things work.
// Out: Maps a subset of the redux state to the properties that will be formatted by a PresentationComponent.
// In: Maps commands coming from a PresentationComponent to a store action, and dispatch the mapped action.

public protocol ContainerComponentDelegate: class {
    func containerComponentChanged()
}

public final class ContainerComponent<State, Action, Command, Properties> {
    public private(set) var properties: Properties
    public weak var delegate: ContainerComponentDelegate?
    private var unsubscribe: (() -> Void)?
    private weak var store: Store<State, Action>?
    private var mapStateToProperties: (State) -> Properties
    private var mapCommandToAction: (Command) -> (Action?)

    public init(
        store: Store<State, Action>,
        mapStateToProperties: @escaping (State) -> Properties,
        mapCommandToAction: @escaping (Command) -> Action?)
    {
        self.mapStateToProperties = mapStateToProperties
        self.mapCommandToAction = mapCommandToAction
        self.store = store
        properties = mapStateToProperties(store.state)
        unsubscribe = store.subscribe(observer: self)
    }

    deinit {
        unsubscribe?()
    }

    public func dispatch(command: Command) {
        if let action = mapCommandToAction(command) {
            store?.dispatch(action: action)
        }
    }
}

extension ContainerComponent: StoreObserver {
    func storeChanged() {
        guard let state = store?.state else { return }
        properties = mapStateToProperties(state)
        delegate?.containerComponentChanged()
    }
}
<file_sep>/ReduxBlueprint/Store.swift
import Foundation

// Redux architecture revolves around a strict unidirectional data flow.
// Redux provides a single store.subscribe method for notifying listeners that the store has updated.

protocol StoreObserver: class {
    func storeChanged()
}

public final class Store<State, Action> {
    private var observers: StoreObservers
    private let reducer: (State, Action) -> State
    private(set) var state: State

    //To specify how the state tree is transformed by actions, you write pure reducers.
    public init(reducer: @escaping (State, Action) -> State, initialState: State) {
        self.reducer = reducer
        self.state = initialState
        self.observers = StoreObservers()
    }

    func subscribe(observer: StoreObserver) -> () -> Void {
        if let offset = observers.index(of: observer) {
            return { [weak self] in self?.observers.remove(at: offset) }
        }
        observers.append(observer)
        let offset = observers.count - 1
        return { [weak self] in self?.observers.remove(at: offset) }
    }

    // The only way to change the state is to emit an action, an object describing what happened.
    // This ensures that neither the views nor the network callbacks will ever write directly to the state.
    // Instead, they express an intent to transform the state.
    func dispatch(action: Action) {
        state = reducer(state, action)
        observers.forEach { $0.storeChanged() }
    }
}

private struct StoreObservers {
    private final class WeakReference {
        weak var value: StoreObserver?

        init(value: StoreObserver) {
            self.value = value
        }
    }

    private var currentIndex: Int = 0
    private var weakReferences: [WeakReference] = []

    var count: Int {
        return weakReferences.filter({ $0.value != nil }).count
    }

    func index(of observer: StoreObserver) -> Int? {
        return weakReferences.index(where: {
            guard let value = $0.value else {
                return false
            }
            return observer === value
        })
    }

    subscript(offset: Int) -> StoreObserver? {
        return weakReferences[offset].value
    }

    mutating func compact() {
        weakReferences = weakReferences.filter { $0.value != nil }
    }

    mutating func append(_ observer: StoreObserver) {
        weakReferences.append(WeakReference(value: observer))
    }

    mutating func remove(at offset: Int) {
        weakReferences.remove(at: offset)
    }
}

extension StoreObservers: Sequence, IteratorProtocol {
    mutating func next() -> StoreObserver? {
        let numberOfValues = count
        guard numberOfValues > 0 && currentIndex < numberOfValues else {
            return nil
        }
        var value: StoreObserver?
        while value == nil, currentIndex < numberOfValues {
            value = weakReferences[currentIndex].value
            currentIndex += 1
        }
        return value
    }
}
<file_sep>/ReduxBlueprint Mac/ReduxBlueprint_Mac.h
#import <Foundation/Foundation.h>

//! Project version number for ReduxBlueprint_Mac.
FOUNDATION_EXPORT double ReduxBlueprint_MacVersionNumber;

//! Project version string for ReduxBlueprint_Mac.
FOUNDATION_EXPORT const unsigned char ReduxBlueprint_MacVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <ReduxBlueprint_Mac/PublicHeader.h>

languages: Swift Markdown Objective-C

repo_language: Swift

repo_name: folivero/ReduxBlueprint


text:
<repo_name>VictorFouquet/Code-Wars-Katas<file_sep>/Escape the Maze - 4kyu (#fundamentals #algorithms)/escape_the_maze.py
def escape(maze):
    print(maze)
    def makeGraph(graph, maze):
        for row in range(0,len(maze)):

            for col in range(0,len(maze[0])):

                if maze[row][col] != "#" :
                    if maze[row][col] != " ":
                        graph["start"] = {
                            "symbol": maze[row][col],
                            "ref": (row, col)
                        }

                    if not (row, col) in graph:
                        graph[(row, col)] = createNode(maze, (row, col))

                    graph = createEdge(graph, maze, (row, col))

        return graph

    def createNode(maze, pos):
        return {
            'ref': pos,
            'row': pos[0],
            'col': pos[1],
            'direction': None,
            'orientation': None,
            'visited': False,
            'neighbors': [],
            'parent': None
        }

    def createEdge(graph, maze, pos):
        adjacencies = getAdjacencies(pos)

        for adj in adjacencies:

            if (adj[0] in range(0, len(maze))
            and adj[1] in range(0,len(maze[0]))
            and maze[adj[0]][adj[1]] != "#"):

                if not adj in graph:
                    graph[adj] = createNode(maze, adj)

                graph[pos]["neighbors"].append(graph[adj])

        return graph

    def getAdjacencies(pos):
        return [
            (pos[0], pos[1]+1),
            (pos[0]+1, pos[1]),
            (pos[0], pos[1]-1),
            (pos[0]-1, pos[1])
        ]

    def findOrientation(symbol):
        orientation = {
            "^": "north",
            ">": "east",
            "v": "south",
            "<": "west"
        }
        return orientation[symbol]

    def eastOriented(current, neighbor):
        if current["col"] < neighbor["col"]:
            return ["F", "east"]

        elif current["col"] > neighbor["col"]:
            return ["BF", "west"]

        elif current["row"] < neighbor["row"]:
            return ["RF", "south"]

        else:
            return ["LF", "north"]

    def westOriented(current, neighbor):
        if current["col"] > neighbor["col"]:
            return ["F", "west"]

        elif current["col"] < neighbor["col"]:
            return ["BF", "east"]

        elif current["row"] > neighbor["row"]:
            return ["RF", "north"]

        else:
            return ["LF", "south"]

    def northOriented(current, neighbor):
        if current["col"] < neighbor["col"]:
            return ["RF", "east"]

        elif current["col"] > neighbor["col"]:
            return ["LF", "west"]

        elif current["row"] < neighbor["row"]:
            return ["BF", "south"]

        else:
            return ["F", "north"]

    def southOriented(current, neighbor):
        if current["col"] > neighbor["col"]:
            return ["RF", "west"]

        elif current["col"] < neighbor["col"]:
            return ["LF", "east"]

        elif current["row"] > neighbor["row"]:
            return ["BF", "north"]

        else:
            return ["F", "south"]

    def findDirection(current, neighbor, orientation):
        if orientation == "east":
            return eastOriented(current, neighbor)

        if orientation == "west":
            return westOriented(current, neighbor)

        if orientation == "north":
            return northOriented(current, neighbor)

        if orientation == "south":
            return southOriented(current, neighbor)

    def exitFound(pos, lenX, lenY):
        if (pos[0] == 0
        or pos[0] == lenX
        or pos[1] == 0
        or pos[1] == lenY):
            return True
        else:
            return False

    def retracePath(graph, current):
        path = []
        while current["parent"] != None:
            if len(current["direction"]) == 2:
                path.insert(0, current["direction"][1])
                path.insert(0, current["direction"][0])

            else:
                path.insert(0, current["direction"])

            current = current["parent"]

        return path

    def BFS(graph, maze):
        queue = []
        lenX = len(maze)-1
        lenY = len(maze[0])-1
        found = False
        current = graph[graph["start"]["ref"]]
        current["visited"] = True
        current["orientation"] = findOrientation(graph["start"]["symbol"])
        queue.append(current)

        while len(queue) > 0:
            current = queue.pop(0)
            orientation = current["orientation"]
            neighbors = current["neighbors"]

            for neighbor in neighbors:
                if neighbor["visited"] == False:
                    parentInfos = findDirection(current, neighbor, orientation)
                    neighbor["parent"] = current
                    neighbor["direction"] = parentInfos[0]
                    neighbor["orientation"] = parentInfos[1]
                    neighbor["visited"] = True
                    queue.append(neighbor)
                    found = exitFound(neighbor["ref"], lenX, lenY)
                if found == True:
                    path = retracePath(graph, neighbor)
                    break

            if found == True:
                return path
                break

        return []

    graph = {}
    graph = makeGraph(graph, maze)
    return BFS(graph, maze)<file_sep>/Path Finder #1: Can you reach the exit? - 4kyu (#algorithms)/reachable_exit.js
function pathFinder(maze){

  function getNeighbors(maze, visited, x, y, l, L) {
    let moves = [[x+1, y], [x, y+1], [x-1, y], [x, y-1]];
    let legalMoves = []
    for (let move of moves){
      if (!visited[move] &&
      move[0] < l && move[0] >= 0 &&
      move[1] < L && move[1] >= 0 &&
      maze[move[0]][move[1]] != "W") {
          legalMoves.push(move);
          visited[move] = true;
      }
    }
    return legalMoves;
  }

  function breadthFirst(maze) {
    var visited = {};
      var queue = [];
      var l = maze.length;
      var L = maze[0].length;
      queue.push([0,0]);
      visited["0,0"] = true

      while (queue.length) {
        var current = queue.shift();
        var neighs = getNeighbors(maze, visited, current[0], current[1], l, L);
        queue.push(...neighs)
      }
      if (visited[[l-1, L-1]]) {
        return true;
      } else {
        return false;
      }
  }

  return breadthFirst(maze.split("\n"));

}<file_sep>/Human readable duration format - 4kyu (#algorithms #formats #strings #dates_time)/human_readable_format.rb
def format_duration(seconds)
  return "now" if seconds == 0
  time = {}; clean_format = []

  time["1year"] = seconds / 31536000; seconds -= time["1year"] * 31536000
  time["2day"] = seconds / 86400; seconds -= time["2day"] * 86400
  time["3hour"] = seconds / 3600; seconds -= time["3hour"] * 3600
  time["4minute"] = seconds / 60; seconds -= time["4minute"] * 60
  time["5second"] = seconds

  time.delete_if { |k, v| v == 0 }.keys.each{ |k, v| (time[k+"s"] = time[k]; time.delete(k)) if time[k] > 1 }
  time.each { |k,v| clean_format << [k, v] }
  clean_format = clean_format.sort
  clean_format.map! { |e| e = "#{e.last} #{e.first[1..-1]}"; p e }
  clean_format.size < 2 ? clean_format[0] : (clean_format[0..-2]*", " + " and #{clean_format[-1]}")
end<file_sep>/The observed PIN - 4kyu (#algorithms)/the_observed_pin.rb
def get_pins(observed)
  return [] if observed.nil?
  puts observed
  nums = {
	  "1" => ["1", "4", "2"],
    "2" => ["1", "2", "3", "5"],
	  "3" => ["2", "3", "6"],
	  "4" => ["1", "4", "5", "7"],
	  "5" => ["4", "2", "6", "8", "5"],
	  "6" => ["3", "5", "6", "9"],
	  "7" => ["4", "7", "8"],
	  "8" => ["7", "5", "9", "0", "8"],
	  "9" => ["9", "6", "8"],
	  "0" => ["0", "8"]
  }
  solutions = []
  observed = observed.chars.map! { |e| nums[e] }
  1.upto(observed.size-1) { |i| observed[0] = observed[0].product(observed[i]).map{|e| e.join} }
  observed.first
end<file_sep>/Path Finder #2: Shortest Path - 4kyu (#algorithms)/shortest_path_finder.js
function pathFinder(maze){

  function BFS(maze) {

    var visited = {};
    var queue = [];
    var l = maze.length;
    var L = maze[0].length;
    var steps = 0;

    visited["0,0"] = "start";
    queue.push([0,0,0]);

    while (queue.length) {

      var current = queue.shift();
      var x = current[0];
      var y = current[1];
      var steps = current[2] + 1;
      var moves = [
        [x+1, y],
        [x, y+1],
        [x-1, y],
        [x, y-1]
      ];

      for (let move of moves) {

        if (!visited[move] &&
        move[0] < l && move[0] >= 0 &&
        move[1] < L && move[1] >= 0 &&
        maze[move[0]][move[1]] != "W") {

          visited[move] = steps;
          move.push(steps);
          queue.push(move);

        }
      }

      if (visited[[l-1, L-1]]) {

        return visited[[l-1, L-1]];

      }

    }

    return false

  }

  if (maze.length == 1) {

    return 0;

  } else {

    return BFS(maze.split("\n"));

  }

}<file_sep>/Sum of Intervals - 4kyu (#algorithms #aggregations #arithmetic #mathematics #integers #numbers)/sum_of_intervals.rb
def sum_of_intervals(intervals)
  i = 1
  arr = intervals.sort
  while i < arr.size
    if arr[i-1].last >= arr[i].first
      (arr[i-1] = (arr[i-1]|arr[i]).minmax; arr.delete_at(i))
    else
      i += 1
    end
  end
  arr.map { |e| e.last-e.first}.sum
end<file_sep>/Permutations - 4kyu (#algorithms #permutations #strings)/README.md
CodeWars Kata "Permutations"
Kata link : https://www.codewars.com/kata/5254ca2719453dcc0b00027d
Kata author : https://www.codewars.com/users/BattleRattle

In this kata you have to create all permutations of an input string and remove duplicates, if present. This means, you have to shuffle all letters from the input in all possible orders.

Examples:

permutations('a'); # ['a']
permutations('ab'); # ['ab', 'ba']
permutations('aabb'); # ['aabb', 'abab', 'abba', 'baab', 'baba', 'bbaa']

The order of the permutations doesn't matter.
<file_sep>/Make a spiral - 3kyu (#algorithms #arrays #control_flow)/make_a_spiral.rb
def spiralize(size)
  def right(arr, first_lign, last_lign, first_col, last_col, first_move)
	if first_col <= last_col
		first_move ? i = first_col-1 : i = first_col - 2
		first_move = false
    arr[first_lign][i+=1] = 1 while i < last_col
		first_lign += 2
		down(arr, first_lign, last_lign, first_col, last_col, first_move)
	else
		arr
	end
end
def down(arr, first_lign, last_lign, first_col, last_col, first_move)
	if first_lign < last_lign +2
		i = first_lign - 2
		arr[i+=1][last_col] = 1 while i < last_lign
		last_col -= 2
		left(arr, first_lign, last_lign, first_col, last_col, first_move)
	else
		arr
	end
end
def left(arr, first_lign, last_lign, first_col, last_col, first_move)
	if first_col <= last_col
		i = last_col + 2
		arr[last_lign][i-=1] = 1 while i > first_col
		last_lign -=2
		up(arr, first_lign, last_lign, first_col, last_col, first_move)
	else
		arr
	end
end
def up(arr, first_lign, last_lign, first_col, last_col, first_move)
	if first_lign < last_lign + 2
		i = last_lign + 2
    arr[i-=1][first_col] = 1 while i > first_lign
		first_col += 2
		right(arr, first_lign, last_lign, first_col, last_col, first_move)
	else
		arr
	end
end
right(Array.new(size){ Array.new(size).map { 0 } }, 0, size-1, 0, size-1, true)
end<file_sep>/Permutations - 4kyu (#algorithms #permutations #strings)/permutations.rb
def permutations(string)
  string.chars.permutation(string.size).map { |e| e.join }.uniq
end<file_sep>/Is that a line - 3kyu (#algorithms)/README.md
CodeWars Kata "Safari Line - Is that a line?"
Kata link : https://www.codewars.com/kata/59c5d0b0a25c8c99ca000237
Kata author : https://www.codewars.com/users/dinglemouse

You are given a grid, which always includes exactly two end-points indicated by X

You simply need to return true/false if you can detect a one and only one "valid" line joining those points.

A line can have the following characters :

    - = left / right
    | = up / down
    + = corner

Rules for valid lines

    The most basic kind of valid line is when the end-points are already adjacent

    X
    X

    XX

    The corner character (+) must be used for all corners (but only for corners).
    It must be possible to follow the line with no ambiguity (lookahead of just one step, and never treading on the same spot twice).
    The line may take any path between the two points.
    Sometimes a line may be valid in one direction but not the other. Such a line is still considered valid.
    Every line "character" found in the grid must be part of the line. If extras are found then the line is not valid.

Examples
Good lines

X---------X

X
|
|
X

   +--------+
X--+        +--+
               |
               X

   +-------------+
   |             |
X--+      X------+

   +-------+
   |      +++---+
X--+      +-+   X

Bad lines

X-----|----X

X
|
+
X

   |--------+
X---        ---+
               |
               X

   +------
   |
X--+      X

      +------+
      |      |
X-----+------+
      |
      X

Hint

Imagine yourself walking a path where you can only see your very next step. Can you know which step you must take, or not?<file_sep>/Find the cheapest path - 3Kyu (#Algorithm#Performance)/cheapest_path.py
def cheapest_path(t, start, finish):

    def addVertex(row, col):
        return {
            'ref': (row, col),
            'row': row,
            'col': col,
            'neighbors': [],
            'parent': None,
            'cost': float("inf"),
            'processed': False
        }

    def addEdge(graph, t, row, col):
        tiles = adjacentTiles(row, col)
        for tile in tiles:
            if (
            tile[0] >= 0 and tile[0] < len(t)
            and tile[1] >= 0 and tile[1] < len(t[row])
            ):
                if not tile in graph:
                    graph[tile] = addVertex(tile[0], tile[1])
                graph[(row, col)]["neighbors"].append(graph[tile])
        return graph

    def adjacentTiles(row, col):
        return [
            (row + 1, col),
            (row, col + 1),
            (row - 1, col),
            (row, col - 1)
        ]

    def retraceCheapestPath(vertex):
        path = []
        while vertex["parent"] != None:
            if vertex["parent"]["row"] > vertex["row"]:
                path.insert(0, "up")

            elif vertex["parent"]["row"] < vertex["row"]:
                path.insert(0, "down")

            elif vertex["parent"]["col"] > vertex["col"]:
                path.insert(0, "left")

            else:
                path.insert(0, "right")

            vertex = vertex["parent"]

        return path

    def dijkstra(t, start, finish):
        n = 0
        unvisited = {}
        processed = {}
        graph = {}
        found = False
        minCost = t[start[0]][start[1]]
        graph[start] = addVertex(start[0],start[1])
        graph[start]["cost"] = minCost
        unvisited[minCost] = [graph[start]]

        while found == False:

            current = unvisited[minCost].pop(0)
            processed[current["ref"]] = True
            graph = addEdge(graph, t, current["row"], current["col"])
            neighbors = current["neighbors"]

            for neighbor in neighbors:
                if neighbor["ref"] == finish:
                    found = True
                actualCost = t[neighbor["row"]][neighbor["col"]] + current["cost"]

                if (not neighbor["ref"] in processed
                and actualCost < neighbor["cost"]):
                    neighbor["cost"] = actualCost
                    neighbor["parent"] = current

                    if not actualCost in unvisited:
                        unvisited[actualCost] = []

                    unvisited[actualCost].append(neighbor)

            if (len(unvisited[minCost]) == 0
            and found == False):
                del unvisited[minCost]

                while not minCost in unvisited:
                    minCost += 1

        return retraceCheapestPath(graph[finish])

    if start == finish:
        return []

    else:
        return dijkstra(t, start, finish)<file_sep>/Four Pass Transport - 1kyu (#algorithms #puzzles #games)/four_pass_transport.js
function fourPass(stations){
  function makeGraph(graph){

  	for (let i=0; i < 10; i++) {

  		for (let j = 0; j < 10; j++){

  			graph[ i + "" + j ] = {

  				ref: i + "" + j,
  				neighbors: getNeighbors(i,j),
  				isStation: false

  			}

  		}

  	}

  }

  function getNeighbors(i, j) {

  	let moves = [
  		[i+1, j],
  		[i, j+1],
  		[i-1, j],
  		[i, j-1]
  	];
  	let neighbors = [];

  	for (let move of moves) {

  		if (move[0] >= 0
  		&& move[0] < 10
  		&& move[1] >= 0
  		&& move[1] < 10) {

  			neighbors.push(move.join(""))

  		}

  	}

  	return neighbors;

  }

  function BFS(graph, start, end, blocked, conflicts, path) {

  	let visited = {};
  	let linkedList = {};
  	let queue = [];
  	let current = graph[start];

  	visited[start] = "start";
  	queue.push(current);

  	while (queue.length) {

  		current = queue.shift();
  		let neighbors = current.neighbors;

  		for (let neighbor of neighbors) {

  			if (blocked[neighbor]) {

  				if (!conflicts.includes(blocked[neighbor])) {

  					conflicts.push(blocked[neighbor]);

  				}

  				if (!conflicts.includes(path)) {

  					conflicts.push(path);

  				}

  			}

  			if (!visited[neighbor] && !blocked[neighbor]) {

  				if (graph[neighbor].isStation && neighbor != end) {
  					continue;
  				}

  				visited[neighbor] = current.ref;
  				queue.push(graph[neighbor]);

  			}

  		}

  		if (visited[end]) {

  			current = end;
  			let len = 0
  			while (visited[current] && visited[current] != "start") {
  				len++
  				linkedList[current] = visited[current];
  				current = visited[current];

  				linkedList["start"] = start;
  				linkedList["end"] = end
  				blocked[current] = path;

  			}
  			linkedList["len"] = len;

  			return [linkedList, blocked];

  		}

  	}

  	return false;

  }

  function assemblePaths(paths, normal) {

  	let finalPath = [];
  	let pathRefs = ["pathA","pathB", "pathC"];

  	for (ref of pathRefs) {

  		let current = paths[ref].end;
  		let provPath = [];

  		while (paths[ref][current]) {

  			if (paths[ref][current] < 10) {

  				provPath.push(parseInt(paths[ref][current][1]));

  			} else {

  				provPath.push(parseInt(paths[ref][current]));

  			}

  			current = paths[ref][current];

  		}
  		if (normal) {
  			finalPath.push(...provPath.reverse())
  		} else {
  			finalPath.push(...provPath)
  		}

  	}

  	return finalPath;

  }

  function permute(arr, start, end, altPaths) {

  	if (start == end) {

  		return(altPaths.push([...arr]));

  	} else {

  		for (let i = start; i < end; i++) {

  			[arr[start], arr[i]] = [arr[i], arr[start]];
  			permute(arr, start+1, end, altPaths);
  			[arr[start], arr[i]] = [arr[i], arr[start]];

  		}

  	}

  }

  var graph = {};
  var blocked = {};
  var conflicts = [];
  var paths = {};
  var allPaths = [];
  var pathFinding
  makeGraph(graph);

  for (let station of stations) {
  	if (station < 10) {
  		graph["0"+station].isStation = true;
  	} else {
  		graph[station].isStation = true;
  	}
  }

  // Tracing most direct paths

  for (let i = 0; i < stations.length-1; i++) {

  	let provStart = stations[i];
  	let provEnd = stations[i+1];
  	let pathRefs = ["pathA", "pathB", "pathC"];

  	if (stations[i] < 10) {
  		provStart = "0" + stations[i];
  	}
  	if (stations[i+1] < 10) {
  		provEnd = "0" + stations[i+1];
  	}

  	graph[provStart].isStation = true;
  	graph[provEnd].isStation = true;

  	pathFinding = BFS(graph, provStart, provEnd, blocked, conflicts, pathRefs[i]);

  	if (pathFinding) {
  		paths[pathRefs[i]] = pathFinding[0];
  		blocked = pathFinding[1];
  	}

  }

  // Resolve conflicts if they exist or assemble shortest possible path

  if (conflicts.length) {

  	var altPaths = [];
  	permute(conflicts, 0, conflicts.length, altPaths)
  	for (let path of altPaths) {
  		blocked = {};
  		var altBlocked = {};
  		conflicts = [];
  		var totLen = 0;
  		var found = 0;
  		var altFound = 0;
  		var altSteps = {};
  		var altPathFinding
  		for (let step of path) {
  			let start, end;
  			switch (step) {
  				case "pathA":
  					start = stations[0];
  					end = stations[1];
  					break
  				case "pathB":
  					start = stations[1];
  					end = stations[2];
  					break
  				case "pathC":
  					start = stations[2];
  					end = stations[3];
  					break
  				default:
  					console.log("daym");
  					break;
  			}
  			let provStart = start;
  			let provEnd = end;
  			if (start < 10) {
  				provStart = "0" + start;
  			}
  			if (end < 10) {
  				provEnd = "0" + end;
  			}

  			graph[provStart].isStation = true;
  			graph[provEnd].isStation = true;
  			pathFinding = BFS(graph, provStart, provEnd, blocked, conflicts, step);
  			if (pathFinding) {
  				found++;
  				paths[step] = pathFinding[0];
  				blocked = pathFinding[1];
  				blocked[provStart] = false;
  				blocked[provEnd] = false;
  			}

  			altPathFinding = BFS(graph, provEnd, provStart, altBlocked, conflicts, step);
  			if (altPathFinding) {
  				altFound++;
  				altSteps[step] = altPathFinding[0];
  				altBlocked = altPathFinding[1];
  				altBlocked[provStart] = false;
  				altBlocked[provEnd] = false;
  			}

  		}
  		if (found == 3) {
  			let finalPath = assemblePaths(paths, true);
  			finalPath.push(stations[3]);
  			allPaths.push(finalPath);
  		} else {
  			continue
  		}
  		if (altFound == 3) {
  			let finalPath = assemblePaths(altSteps, false);
  			finalPath.unshift(stations[0]);
  			allPaths.push(finalPath);
  		} else {
  			continue
  		}

  	}
    if (allPaths.length) {
    	allPaths = allPaths.sort((a,b) => a.length - b.length)
    	return allPaths.shift();
    } else {
      return null;
    }

  } else {

  	let finalPath = assemblePaths(paths);
  	finalPath.push(stations[3])
  	return finalPath;

  }
}
<file_sep>/Stargate SG1: Cute and Fuzzy - 3kyu (#puzzles #games #algorithms # data_structures #dynamic_programming/README.md

    I don't even know what they look like.
    Furling... Sounds cute and fuzzy to me.

    - <NAME> and <NAME>, "Paradise Lost".

Previously on Stargate SG-1

Arriving on P4F-976, SG-1 finally come into contact with the Furlings, one of the four great races within the Milky Way. After several days of deliberation with the Furling Directorate, the Tauri finally have access to the knowledge they have been searching for.

The Furlings, having provided assistance with the Ancient's expansion into the Milky Way, have extensive knowledge of the Stargate Network and it's components. One such component, the Dial Home Device, has caused many disasters at Stargate Command through it's absence. Thankfully, the Furlings have all the necessary blueprints for it's construction, and have handed copies over to the Tauri. After beginning mass production of the control crystals necessary for it's function, Stargate Command has hit a snag. The Ancients had designed the control crystals to function if their inner pathways are as efficient as possible - essentially, the pathways must choose the shortest path between two nodes. Stargate Command has turned to you - a software engineer - to fix their problems.

Your Mission

Given a string containing the current state of the control crystals inner pathways (labeled as "X") and its gaps (labeled as "."), generate the shortest path from the start node (labeled as "S") to the goal node (labeled as "G") and return the new pathway (labeled with "P" characters).
If no solution is possible, return the string "Oh for crying out loud..." (in frustration).

The Rules

    Nodes labeled as "X" are not traversable.
    Nodes labeled as "." are traversable.
    A pathway can be grown in eight directions (up, down, left, right, up-left, up-right, down-left, down-right), so diagonals are possible.
    Nodes labeled "S" and "G" are not to be replaced with "P" in the case of a solution.
    The shortest path is defined as the path with the shortest euclidiean distance going from one node to the next.
    If several paths are possible with the same shortest distance, return any one of them.

Note that the mazes won't always be squares.

Example #1: Valid solution

.S...             .SP..
XXX..             XXXP.
.X.XX      =>     .XPXX
..X..             .PX..
G...X             G...X

Example #2: No solution

S....
XX...
...XX      =>     "Oh for crying out loud..."
.XXX.
XX..G

Note: Your solution will have to be efficient because it will have to deal with a lot of maps and big ones.

Caracteristics of the random tests:

    map sizes from 3x3 to 73x73 (step is 5 from one size to the other, mazes won't always be squares)
    20 random maps for each size.
    Overall, 311 tests to pass with the fixed ones.
<file_sep>/Path FInder #3: The Alpinist - 3kyu (#algorithms)/the_alpinist.rb
def path_finder(maze)
  puts maze
  def check_for_moves(i, n, mod, visited)
    moves = []
    if (i + 1) % mod == 0
      moves.push(i - 1) if !visited[i - 1]
      moves.push(i + mod) if (i + mod < n && !visited[i + mod])
      moves.push(i - mod) if  (i - mod >= 0 && !visited[i - mod])
    elsif i % mod == 0
      moves.push(i + 1) if !visited[i + 1]
      moves.push(i + mod) if (i + mod < n && !visited[i + mod])
      moves.push(i - mod) if  (i - mod >= 0 && !visited[i - mod])
    else
      moves.push(i - 1) if !visited[i - 1]
      moves.push(i + 1) if !visited[i + 1]
      moves.push(i+mod) if (i + mod < n && !visited[i + mod])
      moves.push(i-mod) if  (i - mod >= 0 && !visited[i - mod])
    end
    moves
  end

  def relax_vertice(arr, altitudes, min_climbed, visited, results, i, j)
    new_alt = results[[arr[i], arr[j]]] + min_climbed
    unless visited[i]
      altitudes[new_alt] ? (altitudes[new_alt].unshift(i) if !altitudes[new_alt].include?(i) && !visited[i]) : altitudes[new_alt] = [i]
    end
  end

  results = {}
  (0..9).to_a.combination(2).map { |n| x = n.minmax.reverse.reduce(:-); results[[n[0], n[0]]] = 0; results[n] = x; results[n.reverse] = x }
  results[[9,9]] = 0
  arr = maze.gsub("\n", "").gsub(",", "").chars.map(&:to_i)
  n = arr.size
  return 0 if n == 1
  mod = Math.sqrt(n).round
  inf = 1/0.0
  visited = {}
  altitudes = { 0 => [0], inf => (1..(n-1)).to_a }
  min_climbed = 0
  vertex = 0

  until altitudes[min_climbed][0] == n-1
    i = j = vertex
    check_for_moves(i, n, mod, visited).map { |move| relax_vertice(arr, altitudes, min_climbed, visited, results, move, j) }
    visited[j] = true

    altitudes[min_climbed].delete(i)

    if altitudes[min_climbed].empty?
      altitudes.delete(min_climbed)
      min_climbed = altitudes.min.first
    end
    vertex = altitudes[min_climbed].first
  end
  return min_climbed
end<file_sep>/Find the cheapest path - 3Kyu (#Algorithm#Performance)/README.md
Code Wars Kata "Find the cheapest path"
Kata link : https://www.codewars.com/kata/5abeaf0fee5c575ff20000e4
Kata author : https://www.codewars.com/users/FArekkusu

You should be familiar with the "Find the shortest path" problem. But what if moving to a neighboring coordinate counted not as 1 step but as N steps?

INSTRUCTIONS
Your task is to find the path through the field which has the lowest cost to go through.
As input you will receive:
1) a toll_map matrix (as variable t) which holds data about how expensive it is to go through the given field coordinates
2) a start coordinate (tuple) which holds information about your starting position
3) a finish coordinate (tuple) which holds information about the position you have to get to
As output you should return:
1) the directions list

EXAMPLE

INPUT:
toll_map  |  start  |  finish
          |         |
[         |         |
 [1,9,1], |  (0,0)  |  (0,2)
 [2,9,1], |         |
 [2,1,1], |         |
]         |         |

OUTPUT:
["down", "down", "right", "right", "up", "up"]

CLARIFICATIONS
1) the start and finish tuples have the (x, y) format which means start = (x_1, y_1) and finish = (x_2, y_2), start_pos = field[x_1][y_1] and finish_pos = field[x_2][y_2]
2) the total cost is increased after leaving the matrix coordinate, not entering it
3) the field will be rectangular, not necessarily a square
4) the field will always be of correct shape
5) the actual tests will check total_cost based on your returned directions list, not the directions themselves, so you shouldn't worry about having multiple possible solutions
<file_sep>/Path Finder #1: Can you reach the exit? - 4kyu (#algorithms)/README.md
CodeWars Kata "Path Finder #1: Can you reach the exit?"
Kata link : https://www.codewars.com/kata/5765870e190b1472ec0022a2
Kata author : https://www.codewars.com/users/evk

You are at position [0, 0] in maze NxN and you can only move in one of the four cardinal directions (i.e. North, East, South, West). Return true if you can reach position [N-1, N-1] or false otherwise.

Empty positions are marked .. Walls are marked W. Start and exit positions are empty in all test cases.<file_sep>/Four Pass Transport - 1kyu (#algorithms #puzzles #games)/README.md
CodeWars Kata "Four Pass Transport"
Kata link : https://www.codewars.com/kata/5aaa1aa8fd577723a3000049
Kata author : https://www.codewars.com/users/docgunthrop

The eccentric candy-maker, <NAME>, is building a new candy factory to produce his new 4-flavor sugar pops. The candy is made by placing a piece of candy base onto a conveyer belt which transports the candy through four separate processing stations in sequential order. Each station adds another layer of flavor.

Due to an error in the factory blueprints, the four stations have been constructed in incorrect locations. It's too costly to disassemble the stations, so you've been called in.

Arrange the directional path of the conveyer belt so that it passes through each of the stations in sequential order while also traveling the shortest distance possible.
Input

An array consisting of the locations of each station on the factory floor, in order. The factory floor is a 10 x 10 matrix (with 0 starting index).
Output

Your function should return the path of the conveyer belt as an array.
If a valid configuration is not possible, return null or None.

The position values in the input and output arrays will consist of integers in the range 0 - 99, inclusive. These integers represent a position on the factory floor.
For example, the position [0,8] is given as 8, and [4,6] is given as 46
Technical Details

    The conveyer belt must run through each station once and in ascending order
    The conveyer belt must not intersect/overlap itself
    The distance covered by the conveyer belt must be the minimum necessary to complete the task
    Full Test Suite: 30 fixed tests, 100 random tests (2000 in java)
    Inputs will always be valid and each test will have zero or more possible solutions..

Test Example
4 stations

//INPUT - reference image A
let stations = [0,65,93,36];
fourPass(stations);

//OUTPUT #1 - reference image B
// [0, 1, 2, 3, 4, 5, 15, 25, 35, 45, 55, 65, 64, 63, 73, 83, 93, 94, 95, 96, 86, 76, 66, 56, 46, 36]

//OUTPUT #2 - reference image C
// [0, 10, 20, 30, 40, 50, 60, 61, 62, 63, 64, 65, 75, 85, 84, 83, 93, 94, 95, 96, 86, 76, 66, 56, 46, 36]

If you enjoyed this kata, be sure to check out my other katas https://www.codewars.com/users/docgunthrop/authored.<file_sep>/Sudoku Solution Validator - 4kyu (#algorithms #data_structures #validation)/sudoku_solution_validator.rb
def validSolution(board)
  lign_checker = col_checker = block_checker = 0
  block_rows = []
  final_blocks = []
  valid = (1..9).to_a

  board.map { |e| lign_checker += 1 if (valid - e).length == 0}
  return false if lign_checker != 9

  board.transpose.map { |e| col_checker += 1 if (valid - e).length == 0}
  return false if col_checker != 9

  3.times { block_rows << board.slice!(0, 3).transpose}
  block_rows.each{ |e| 3.times { final_blocks << e[0..2].flatten } }
  final_blocks.each { |e| block_checker += 1 if  (valid - e).length == 0 }
  return block_checker == 9

end<file_sep>/Is that a line - 3kyu (#algorithms)/is_that_a_line.js
function line(grid) {
  var graph = {numberOfNodes: 0};
  var queue = [];
  var target = [];
  var current, neighbors, start, nCross, visited;
  var found = false;

  for (let i = 0; i < grid.length; i ++){

  	for (let j = 0; j < grid[i].length; j++) {

  		if (grid[i][j] != " "){

  			graph.numberOfNodes++;
  			graph[[i,j]] = {
  				neighbors: [],
  				ref: i+ "," +j,
  				type: grid[i][j],
  				comingFrom : null,
  				visited: false
  			}
  			current = graph[[i,j]];

  			if (grid[i][j] == "X") {

  				current.isTarget = true;
  				target.push([i,j]);

  			}

  			if (grid[i][j] == "|" &&
  					i+1 < grid.length &&
  						grid[i+1][j] != " " &&
  							grid[i+1][j] != "-") {

  				current.neighbors.push({ref: [i+1, j], move: "u"});

  			}

  			if (grid[i][j] == "|" &&
  					i-1 >= 0 &&
  						grid[i-1][j] != " " &&
  							grid[i-1][j] != "-") {

  				current.neighbors.push({ref: [i-1, j], move: "d"});

  			}

  			if (grid[i][j] == "-" &&
  					j+1 < grid[i].length &&
  						grid[i][j+1] != " " &&
  							grid[i][j+1] != "|") {

  				current.neighbors.push({ref: [i, j+1], move: "l"});

  			}

  			if (grid[i][j] == "-" &&
  					j-1 >= 0 &&
  						grid[i][j-1] != " " &&
  							grid[i][j-1] != "|") {

  				current.neighbors.push({ref: [i, j-1], move: "r"});

  			}

        if (grid[i][j] == "+" ||
  					current.isTarget){

  				if (i+1 < grid.length &&
  					grid[i+1][j] != " " &&
  						grid[i+1][j] != "-") {

  					current.neighbors.push({ref: [i+1, j], move: "u"});

  				}

  				if (i-1 >= 0 &&
  					grid[i-1][j] != " " &&
  						grid[i-1][j] != "-") {

  					current.neighbors.push({ref: [i-1, j], move: "d"});

  				}

  				if (j+1 < grid[i].length &&
  						grid[i][j+1] != " " &&
  							grid[i][j+1] != "|") {

  					current.neighbors.push({ref: [i, j+1], move: "l"});

  				}

  				if (j-1 >= 0 &&
  						grid[i][j-1] != " " &&
  							grid[i][j-1] != "|") {

  					current.neighbors.push({ref: [i, j-1], move: "r"});

  				}

  			}

  			if (!current.neighbors.length) {
  				return false;
  			}

  		}
  	}
  }

  start = target.shift();
  graph[start].visited = true;
  neighbors = graph[start].neighbors;
  visited = 1;

  for (let neighbor of neighbors) {
  	graph[neighbor.ref].comingFrom = neighbor.move;
  	queue.push(graph[neighbor.ref]);
  }

  while (queue.length) {

  	current = queue.shift();
  	current.visited = true;
    visited++;
  	neighbors = current.neighbors.filter(neigh => !graph[neigh.ref].visited);

  	if (current.type == "+"){

      if (neighbors.length == 3) {
        nCross = 0;
        for (let neigh of neighbors) {
          if (graph[neigh.ref].type == "+") {
            nCross++;
          }
        }
        if (nCross == neighbors.length) {
          return false
        }
      }

      if (current.comingFrom == "d" ||
  				current.comingFrom == "u") {
  			neighbors = neighbors.filter(neigh => neigh.move == "r" || neigh.move == "l");
  		} else {
  			neighbors = neighbors.filter(neigh => neigh.move == "u" || neigh.move == "d");
  		}

      if (neighbors.length == 2) {

  			neighbors = neighbors.sort(function(a,b) {
  				a = (target[0][0]-a.ref[0])**2 + (target[0][1]-a.ref[1])**2;
  				b = (target[0][0]-b.ref[0])**2 + (target[0][1]-b.ref[1])**2;
  				return a-b;
  			});
  			neighbors.shift();
  		}

    }

    if (!neighbors.length && !current.isTarget) {
      return false;
    }

    if (current.isTarget && queue.length) {
  		return false;
  	} else if (current.isTarget && !queue.length && visited == graph.numberOfNodes) {
  		return true;
  	}

    for (let neighbor of neighbors) {
  		graph[neighbor.ref].comingFrom = neighbor.move;
  		queue.unshift(graph[neighbor.ref]);
  	}

  }
  return false;
}<file_sep>/Pyramid Slide Down - 4kyu (#algorithms #functionnal_programming #declarative_programming #high_order_programming #control_flow/pyramid_slide_down.rb
def longest_slide_down(pyramid)
  i = pyramid.size - 2
  while i >= 0
    pyramid[i].map!.with_index{ |e, j| e += [pyramid[i+1][j], pyramid[i+1][j+1]].max}
    i-=1
  end
  pyramid[0][0]
end<file_sep>/The Lift - 3kyu (#algorithms)/the_lift.js
var theLift = function(queues, capacity) {
  var calls = queues.map(a => a.length > 0);
  var lift = []
  var path = [0]

  while (calls.includes(true)) {

    for (let i = 0; i < queues.length; i++) {
      if (lift.includes(i)) {
        path.push(i);
        while (lift.includes(i)) {
          lift.splice(lift.indexOf(i), 1)
        }
      }
      if (queues[i].length > 0) {
        let checker = lift.length;
        for (let j = 0; j < queues[i].length; j++){
          if (queues[i][j] > i) {
            if (lift.length == capacity) {
              if (path[path.length-1]!= i) {
                path.push(i);
              }
              break
            } else {
              lift.push(queues[i][j])
              queues[i].splice(j, 1);
              if (queues[i].length > 0){
                j--;
              } else {
                calls[i] = false;
              }
            }
          }
        }
        if (checker != lift.length) {
          if (path[path.length-1] != i) {
            path.push(i);
          }
        }
      }
    }

    for (let i = queues.length-1; i >= 0; i--) {
      if (lift.includes(i)) {
        path.push(i);
        while (lift.includes(i)) {

          lift.splice(lift.indexOf(i), 1)
        }
      }
      if (queues[i].length > 0) {
        let checker = lift.length;
        for (let j = 0; j < queues[i].length; j++){
          if (queues[i][j] < i) {
            if (lift.length == capacity) {
              if (path[path.length-1]!= i) {
                path.push(i);
              }
              break
            } else {
              lift.push(queues[i][j])
              queues[i].splice(j, 1);
              if (queues[i].length > 0){
                j--;
              } else {
                calls[i] = false;
              }
            }
          }
        }
        if (checker != lift.length) {
          if (path[path.length-1] != i) {
            path.push(i);
          }
        }
      }
    }

  }

  if (path[path.length-1]!=0) {path.push(0)}
  return path

}<file_sep>/Shortest Knight Path - 4kyu (#algorithms)/shortest_knight_path.rb
def knight(start, finish)
  puts start, finish
  def search_for_case(start, finish)
    @board = ("a".."h").to_a.map { |letter| (1..8).to_a.map { |number| "#{letter}#{number}" } }.transpose.reverse
    @valid = (0..7).to_a
    @seen = [start]
    @next_possibles = [[[start, 8 - start[1].to_i, (start[0].ord-97)]]]
    i = 1
    @next_possibles[i] = []
    move(finish, i)
  end

  def move(finish, i)
    until @next_possibles.flatten.include?(finish)
      @next_possibles[i-1].each { |board_case| find_possibles(board_case[1], board_case.last, i) }
      i+=1
      @next_possibles[i] = []
    end
    i - 1
  end

  def find_possibles(x, y, i)
    [go_up(x, y, i), go_right(x,y, i), go_down(x, y, i), go_left(x, y, i)]
  end

  def go_up(x, y, i)
    if @valid.include?(x-2)
      if @valid.include?(y-1)
        (@next_possibles[i] << [@board[x-2][y-1], x-2, y-1]; @seen << @board[x-2][y-1]) if !@seen.include?(@board[x-2][y-1])
      end
      if @valid.include?(y+1)
        (@next_possibles[i] << [@board[x-2][y+1], x-2, y+1]; @seen << @board[x-2][y+1]) if !@seen.include?(@board[x-2][y+1])
      end
    end
  end

  def go_right(x, y, i)
    if @valid.include?(y+2)
      if @valid.include?(x-1)
        (@next_possibles[i] << [@board[x-1][y+2], x-1, y+2]; @seen << @board[x-1][y+2]) if !@seen.include?(@board[x-1][y+2])
      end
      if @valid.include?(x+1)
        (@next_possibles[i] << [@board[x+1][y+2], x+1, y+2]; @seen << @board[x+1][y+2]) if !@seen.include?(@board[x+1][y+2])
      end
    end
  end

  def go_down(x, y, i)
    if @valid.include?(x+2)
      if @valid.include?(y-1)
        (@next_possibles[i] << [@board[x+2][y-1], x+2, y-1]; @seen << @board[x+2][y-1]) if !@seen.include?(@board[x+2][y-1])
      end
      if @valid.include?(y+1)
        (@next_possibles[i] << [@board[x+2][y+1], x+2, y+1]; @seen << @board[x+2][y+1]) if !@seen.include?(@board[x+2][y+1])
      end
    end
  end

  def go_left(x, y, i)
    if @valid.include?(y-2)
      if @valid.include?(x-1)
        (@next_possibles[i] << [@board[x-1][y-2], x-1, y-2]; @seen << @board[x-1][y-2]) if !@seen.include?(@board[x-1][y-2])
      end
      if @valid.include?(x+1)
        (@next_possibles[i] << [@board[x+1][y-2], x+1, y-2]; @seen << @board[x+1][y-2]) if !@seen.include?(@board[x+1][y-2])
      end
    end
  end

  search_for_case(start, finish)

end<file_sep>/Snail - 4kyu (#algorithms #arrays)/snail.rb
def snail(array)
  if array[0].empty?
    return []
  elsif array.size == 1
    return array[0]
  end
  x = y = f_row = f_col = 0; l_row = l_col = array.size-1
  dir = "right"; new_arr = []
  while f_col <= l_col && f_row <= l_row
	  case dir
		  when "right"
			  new_arr << array[x][y]
			  y += 1; (dir = "down"; f_row +=1) if y == l_col
		  when "down"
			  new_arr << array[x][y]
			  x += 1; (dir = "left"; l_col -= 1) if x == l_row
		  when "left"
			  new_arr << array[x][y]
			  y -= 1; (dir = "up"; l_row -= 1) if y == f_col
		  when "up"
			  new_arr << array[x][y]
			  x -= 1; (dir = "right"; f_col += 1) if x == f_row
	  end
  end
  new_arr << array[x][y]
  new_arr
end<file_sep>/Get to the Choppa - 3kyu (#algorithms #games #puzzles #graphs #data_structures)/get_to_the_choppa.py
def find_shortest_path(grid, start_node, end_node):

    if len(grid) == 0:
        return []

    queue = []
    visited = {start_node.position: True}
    linkedList = {}
    path = []
    queue.append(start_node)
    found = False

    while len(queue) > 0:
        current = queue.pop(0)
        row = current.position.x
        col = current.position.y
        moves = [
            (row+1, col),
            (row, col+1),
            (row-1,col),
            (row,col-1)
        ]

        for move in moves:

            if (move[0] in range(0, len(grid))
            and move[1] in range (0, len(grid[0]))
            and grid[move[0]][move[1]].passable == True
            and not move in visited):

                neighbor = grid[move[0]][move[1]]
                queue.append(grid[move[0]][move[1]])
                visited[move] = True
                linkedList[move] = (current.position.x, current.position.y)

                if move == end_node.position:
                    found = True

        if found == True:
            break

    current = (end_node.position.x, end_node.position.y)

    while current != (start_node.position.x, start_node.position.y):
        path.insert( 0, grid[current[0]][current[1]] )
        current = linkedList[current]

    path.insert(0, start_node)

    return path<file_sep>/Rail Fence Cypher : Encoding and Decoding - 3kyu (#algorithms #ciphers  #cryptography #security #strings)/rail_fence_cipher.py
def encode_rail_fence_cipher(string, n):
    rail = [['\n' for i in range(len(string))]
                  for j in range(n)]
    dir_down = False
    row, col = 0, 0

    for i in range(len(string)):

        if (row == 0) or (row == n - 1):
            dir_down = not dir_down

        rail[row][col] = string[i]
        col += 1

        if dir_down:
            row += 1
        else:
            row -= 1

    result = []
    for i in range(n):
        for j in range(len(string)):
            if rail[i][j] != '\n':
                result.append(rail[i][j])
    return("" . join(result))

def decode_rail_fence_cipher(string, n):
    rail = [['\n' for i in range(len(string))]
                  for j in range(n)]

    dir_down = None
    row, col = 0, 0

    for i in range(len(string)):
        if row == 0:
            dir_down = True
        if row == n - 1:
            dir_down = False

        rail[row][col] = '*'
        col += 1

        if dir_down:
            row += 1
        else:
            row -= 1

    index = 0
    for i in range(n):
        for j in range(len(string)):
            if ((rail[i][j] == '*') and
               (index < len(string))):
                rail[i][j] = string[index]
                index += 1

    result = []
    row, col = 0, 0
    for i in range(len(string)):

        if row == 0:
            dir_down = True
        if row == n-1:
            dir_down = False

        if (rail[row][col] != '*'):
            result.append(rail[row][col])
            col += 1

        if dir_down:
            row += 1
        else:
            row -= 1
    return("".join(result)) <file_sep>/Twice Linear - 4kyu (#algorithms #numbers #mathematics)/README.md
CodeWars Kata "Twice Linear"
Kata link : https://www.codewars.com/kata/5672682212c8ecf83e000050
Kata author : https://www.codewars.com/users/g964

Consider a sequence u where u is defined as follows:

    1 - The number u(0) = 1 is the first one in u.
    2 - For each x in u, then y = 2 * x + 1 and z = 3 * x + 1 must be in u too.
    3 - There are no other numbers in u.

Ex: u = [1, 3, 4, 7, 9, 10, 13, 15, 19, 21, 22, 27, ...]

1 gives 3 and 4, then 3 gives 7 and 10, 4 gives 9 and 13, then 7 gives 15 and 22 and so on...
Task:

Given parameter n the function dbl_linear (or dblLinear...) returns the element u(n) of the ordered (with <) sequence u (so, there are no duplicates).
Example:

dbl_linear(10) should return 22
Note:

Focus attention on efficiency
<file_sep>/Stargate SG1: Cute and Fuzzy - 3kyu (#puzzles #games #algorithms # data_structures #dynamic_programming/stargate_sg1.js
function wire_DHD_SG1(existingWires) {
  var start, goal;
  var str = existingWires.split("\n");
  var l = str.length;
  var L = str[0].length;
  var numberOfNodes = 0
  var open = {};
  var graph = {};
  var found = false;
  var minPath = "0";

  for (let i = 0; i < str.length; i++) {
  	str[i] = str[i].split("");
  	for (let j = 0; j < str[i].length; j ++) {
  		let content = str[i][j];
  		let nodeRef = i + "," + j;
  		if (content != "X" && !graph[nodeRef]) {
  			numberOfNodes ++;
  			graph[nodeRef] = {
  				row: i,
  				col: j,
  				g: Infinity,
  	  		h: Infinity,
  	  		f: Infinity,
  	  		neighbors: [],
  	  		parent: "null",
  	  		processed: false,
  				isStart: false,
  				isGoal: false
  			}

  			if (j+1 < L) {
  				if (i + 1 < l && str[i+1][j+1] != "X") {
  					graph[nodeRef].neighbors.push({
  						ref: i+1 + "," + (j+1),
  						row: i+1,
  						col: j+1,
  						weight: 1.4
  					})
  				}

  				if (i - 1 >= 0 && str[i-1][j+1] != "X") {
  					graph[nodeRef].neighbors.push({
  						ref: i-1 + "," + (j+1),
  						row: i-1,
  						col: j+1,
  						weight: 1.4
  					})
  				}
  				if (str[i][j+1] != "X") {
  					graph[nodeRef].neighbors.push({
  						ref: i + "," + (j+1),
  						row: i,
  						col: j+1,
  						weight: 1
  					})
  				}
  			}

  			if (j-1 >= 0) {
  				if (i + 1 < l && str[i+1][j-1] != "X") {
  					graph[nodeRef].neighbors.push({
  						ref: i+1 + "," + (j-1),
  						row: i+1,
  						col: j-1,
  						weight: 1.4
  					})
  				}

  				if (i - 1 >= 0 && str[i-1][j-1] != "X") {
  					graph[nodeRef].neighbors.push({
  						ref: i-1 + "," + (j-1),
  						row: i-1,
  						col: j-1,
  						weight: 1.4
  					})
  				}
  				if (str[i][j-1] != "X") {
  					graph[nodeRef].neighbors.push({
  						ref: i + "," + (j-1),
  						row: i,
  						col: j-1,
  						weight: 1
  					})
  				}
  			}

  			if (i+1 < l && str[i+1][j] != "X") {
  				graph[nodeRef].neighbors.push({
  					ref: i+1 + "," + j,
  					row: i+1,
  					col: j,
  					weight: 1
  				})
  			}
  			if (i-1 >= 0 && str[i-1][j] != "X") {
  				graph[nodeRef].neighbors.push({
  					ref: i-1 + "," + j,
  					row: i-1,
  					col: j,
  					weight: 1
  				})
  			}

  			if (content == "S") {
  				start = nodeRef;
  				graph[nodeRef].isStart = true;
  			}
  			if (content == "G") {
  				goal = nodeRef;
  				graph[nodeRef].isGoal = true
  			}
  		}
  	}
  }

  graph[start].g = 0;
  graph[start].h = Math.sqrt((graph[goal].row - graph[start].row)**2 + (graph[goal].col - graph[start].col)**2);
  graph[start].f = graph[start].g + graph[start].h;
  graph[goal].h = 0;

  var current = graph[start];
  open[minPath] = [current];

  while (open[minPath]) {
  	if (found) {
  		break;
  	}
  	current = open[minPath].shift();
  	var nodeRef = current.row + "," + current.col;
  	var neighs = graph[nodeRef].neighbors;
  	graph[nodeRef].processed = true;
  	for (let neigh of neighs) {
  		if (!graph[neigh.ref].processed) {
  			if (graph[neigh.ref].isGoal) {
  				graph[goal].parent = {ref: nodeRef, row: current.row, col: current.col};
  				found = true;
  				break;
  			}
  			let cumulatedDist = graph[nodeRef].g + neigh.weight;
  			let heuristic = Math.sqrt((graph[goal].row - graph[neigh.ref].row)**2 + (graph[goal].col - graph[neigh.ref].col)**2);
  			let totalWeight = cumulatedDist + heuristic
  			if (totalWeight < graph[neigh.ref].f) {
  				graph[neigh.ref].parent = {ref: nodeRef, row: current.row, col: current.col};
  				graph[neigh.ref].g = cumulatedDist;
  				graph[neigh.ref].h = heuristic;
  				graph[neigh.ref].f = cumulatedDist + heuristic;
  				if (open[totalWeight + ""]) {
  					open[totalWeight + ""].push(neigh);
  				} else {
  					open[totalWeight + ""] = [neigh]
  				}
  			}

  		}
  	}
  	if (!open[minPath].length) {
  		delete open[minPath];
  		minPath = Math.min(...Object.keys(open));
  	}
  }

  if (!found) {
    return "Oh for crying out loud...";
  }

  var path = [];
  let backtracked = graph[graph[goal].parent.ref];

  while (!backtracked.isStart) {
  	ref = backtracked.row + "," + backtracked.col
  	str[backtracked.row][backtracked.col] = "P";
  	path.push(ref);
  	backtracked = graph[backtracked.parent.ref];
  }

  return str.map(a=> a.join("")).join("\n");

}<file_sep>/ASCII Games : Warning: Ice! - 3kyu (#puzzles #games #ascii #character_encodings #formats)/ice_maze_solver.js
function IceMazeSolver(map) {
  var graph = {numberOfNodes: 0};
  var queue = [];
  var path = [];
  var origin, current, next, start, goal, dist, steps, directions, direction;
  var found = false
  var str = map.split("\n");
  var oposite = {"d": "u", "u": "d", "l": "r", "r": "l"};

  for (let i = 0; i < str.length; i ++){

  	str[i] = str[i].split("");

  	for (let j = 0; j < str[i].length; j++) {
  		if (str[i][j] != "#"){

  			graph[[i,j]] = {
  				neighbors: {},
  				ref: i+ "," +j,
  				comingFrom: null,
  				parent: null,
  				steps: Infinity,
  				distance: Infinity,
  				visited: false
  			}
  			graph.numberOfNodes++;

  			if (i+1 < str.length &&
  				str[i+1][j] != "#") {

  				graph[[i,j]].neighbors["d"] = i+1 + "," +j;

  			}

  			if (j+1 < str[i].length &&
  				str[i][j+1] != "#") {

  				graph[[i,j]].neighbors["r"] = i + "," + (j+1);

  			}

  			if (i-1 >= 0 &&
  				str[i-1][j] != "#") {

  				graph[[i,j]].neighbors["u"] = i-1 + "," +j;

  			}

  			if (j-1 >= 0 &&
  				str[i][j-1] != "#") {

  				graph[[i,j]].neighbors["l"] = i + "," + (j-1);

  			}

  			if (str[i][j] == "x") {
  				graph[[i,j]].isGrip = true;
  			}

  			if (str[i][j] == "S") {
  				graph[[i,j]].isStart = true;
  				graph[[i,j]].distance = 0;
  				graph[[i,j]].steps = 0;
  				start = [i, j];
  			}

  			if (str[i][j] == "E") {
  				graph[[i,j]].isGoal = true;
  				goal = [i, j];
  			}
  		}
  	}
  }

  directions = Object.keys(graph[start].neighbors);
  current = graph[start]

  for (let dir of directions) {
  	graph[current.neighbors[dir]].parent = current;
  	graph[current.neighbors[dir]].comingFrom = dir;
  	queue.push([current.ref, dir]);
  }

  direction = directions.pop();

  let m = 0;

  while(queue.length && m < 5000){
  	next = queue.shift()
  	graph[next[0]].visited = true;
  	current = graph[next[0]];
  	origin = current;
  	direction = next[1];
  	dist = current.distance;

  	while (current.neighbors[direction]) {
  		m++;
  		dist++;
  		current = graph[current.neighbors[direction]]
  		if (current.isGrip) {
  			break;
  		}
  		if (current.isGoal) {
  			found = true;
  			break;
  		}
  	}

  	if (current.visited) {

  		if (current.steps > origin.steps + 1) {
  			current.parent = origin;
  			current.distance = origin.distance + dist;
  			current.steps = origin.steps + 1;
  			current.comingFrom = direction;

  		} else if (current.steps == origin.steps + 1 &&
  			current.distance > dist) {
  			current.parent = origin;
  			current.distance = dist;
  			current.steps = origin.steps + 1;
  			current.comingFrom = direction;
  		}

  	} else {

  		current.visited = true;
  		current.parent = origin;
  		current.distance = dist;
  		current.steps = origin.steps + 1;
  		current.comingFrom = direction;

  		directions = Object.keys(
  				current.neighbors
  					).filter(
  						dir=> dir !== oposite[direction]
  						);
  		for (let dir of directions) {
  			queue.push([current.ref, dir])
  		}
  		directions = [];
  	}

  }

  if (found) {
  	current = graph[goal];
  	while (current.parent) {
  		path.unshift(current.comingFrom);
  		current = current.parent;
  	}
  	return path;
  }

  return null;

}<file_sep>/Strip Comments - 4kyu (#algorithms #strings)/strip_comments.js
function solution(input, markers) {
  let n = 0, i = 0;
  input = input.split("\n").map(lign => lign.split(''));
  for (i=0; i < input.length; i++){
    for (n=0; n < input[i].length; n++){
      if (markers.includes(input[i][n])){
        input[i].splice(n, input[i].length - n);
        if (input[i][input[i].length -1] == " "){
          input[i].pop();
        }
      }
    }
    input[i] = input[i].join('')
  }
  return input.join("\n")
};<file_sep>/Bloxorz Solver - 3kyu (#Algorithms#Games#Puzzles)/bloxorz_solver.py
def blox_solver(ar):
    xMax = len(ar)
    yMax = len(ar[0])
    graph = {}
    for row in range (0, xMax):
        for col in range (0, yMax):
            if ar[row][col] == "B":
                start = ( (row, col), (row, col) )
            elif ar[row][col] == "X":
                end = ( (row, col), (row, col) )

            positions = {
                ((row, col), (row,col)) :
                    [
                        ((row+1, col), (row+2,col)),
                        ((row-2, col), (row-1,col)),
                        ((row, col+1), (row,col+2)),
                        ((row, col-2), (row,col-1))
                    ],
                ((row, col), (row+1,col)) :
                    [
                        ((row, col+1), (row+1,col+1)),
                        ((row, col-1), (row+1,col-1)),
                        ((row-1, col), (row-1,col)),
                        ((row+2, col), (row+2,col))
                    ],
                ((row-1, col), (row,col)) :
                    [
                        ((row-1, col+1), (row,col+1)),
                        ((row-1, col-1), (row,col-1)),
                        ((row-2, col), (row-2,col)),
                        ((row+1, col), (row+1,col))
                    ],
                ((row, col), (row,col+1)) :
                    [
                        ((row-1, col), (row-1,col+1)),
                        ((row+1, col), (row+1,col+1)),
                        ((row, col+2), (row,col+2)),
                        ((row, col-1), (row,col-1))
                    ],
                ((row, col-1), (row,col)) :
                    [
                        ((row-1, col-1), (row-1,col)),
                        ((row+1, col-1), (row+1,col)),
                        ((row, col-2), (row,col-2)),
                        ((row, col+1), (row,col+1))
                    ]
            }

            for position in positions:
                aX = position[0][0]
                bX = position[1][0]
                aY = position[0][1]
                bY = position[1][1]
                if (aX in range(0, xMax)
                and bX in range(0, xMax)
                and aY in range(0,yMax)
                and bY in range(0,yMax)
                and ar[aX][aY] != "0"
                and ar[bX][bY] != "0"):

                    if not position in graph:
                        graph[position] = {
                            "aX": aX,
                            "aY": aY,
                            "bX": bX,
                            "bY": bY,
                            "ref": position,
                            "neighbors": [],
                            "parent": None,
                            "visited": False
                        }

                    for neighbor in positions[position]:
                        neigaX = neighbor[0][0]
                        neigbX = neighbor[1][0]
                        neigaY = neighbor[0][1]
                        neigbY = neighbor[1][1]
                        if (neigaX in range(0, xMax)
                        and neigbX in range(0, xMax)
                        and neigaY in range(0, yMax)
                        and neigbY in range(0, yMax)
                        and ar[neigaX][neigaY] != "0"
                        and ar[neigbX][neigbY] != "0"):
                            if not neighbor in graph:
                                graph[neighbor] = {
                                    "aX": neigaX,
                                    "aY": neigaY,
                                    "bX": neigbX,
                                    "bY": neigbY,
                                    "ref": neighbor,
                                    "neighbors": [],
                                    "parent": None,
                                    "visited": False
                                }
                            graph[position]["neighbors"].append(graph[neighbor])

    found = False
    queue = []
    current = graph[start]
    path = []
    current["visited"] = True
    queue.append(current)
    while len(queue) > 0:
        current = queue.pop(0)
        neighbors = current["neighbors"]
        for neighbor in neighbors:
            if neighbor["visited"] == False:
                neighbor["visited"] = True
                neighbor["parent"] = current
                queue.append(neighbor)
            if neighbor["ref"] == end:
                found = True
                break
        if found == True:
            break
    current = graph[end]

    while current["parent"] != None:
        if (current["parent"]["aX"] > current["aX"]
        or current["parent"]["bX"] > current["bX"]):
            path.insert(0, "U")
        elif (current["parent"]["aX"] < current["aX"]
        or current["parent"]["bX"] < current["bX"]):
            path.insert(0, "D")
        elif (current["parent"]["aY"] < current["aY"]
        or current["parent"]["bY"] < current["bY"]):
            path.insert(0, "R")
        else:
            path.insert(0, "L")
        current = current["parent"]

    return "".join(path)<file_sep>/Escape the Maze - 4kyu (#fundamentals #algorithms)/README.md
CodeWars Kata "Escape the maze"
Kata link : https://www.codewars.com/kata/5877027d885d4f6144000404
Kata author : https://www.codewars.com/users/cyril-lemaire

That's terrible! Some evil korrigans have abducted you during your sleep and threw you into a maze of thorns in the scrubland D:
But have no worry, as long as you're asleep your mind is floating freely in the sky above your body.

    Seeing the whole maze from above in your sleep, can you remember the list of movements you'll have to do to get out when you awake?

Input

You are given the whole maze maze as a 2D grid, more specifically in your language:

an array of strings

maze[0][0] is the top left-hand corner

maze[maze.length - 1][maze[0].length - 1] is the bottom right-hand corner

Inside this 2D grid:

    ' ' is some walkable space
    '#' is a thorn bush (you can't pass through)
    '^', '<', 'v' or '>' is your sleeping body facing respectively the top, left, bottom or right side of the map.

Output

Write the function escape that returns the list/array of moves you need to do relatively to the direction you're facing in order to escape the maze (you won't be able to see the map when you wake up). as an array of the following instructions:

    'F' move one step forward
    'L' turn left
    'R' turn right
    'B' turn back

        Note: 'L','R', and 'B' ONLY perform a rotation and will not move your body

If the maze has no exit, return an empty array.

    This is a real maze, there is no "escape" point. Just reach the edge of the map and you're free!
    You don't explicitely HAVE to find the shortest possible route, but you're quite likely to timeout if you don't ;P
    Aside from having no escape route the mazes will all be valid (they all contain one and only one "body" character and no other characters than the body, "#" and " ". Besides, the map will always be rectangular, you don't have to check that either)

<file_sep>/Strings Mix - 4kyu (#fundamentals #strings)/string_mix.rb
def mix(s1, s2)
  letters = ('a'..'z').to_a.select { |letter| s1.count(letter) > 1 || s2.count(letter) > 1 }
  letters.map! do |letter|
  	case s1.count(letter) <=> s2.count(letter)
  	when 1 then "1:#{letter * s1.count(letter)}"
  	when 0 then "=:#{letter * s1.count(letter)}"
  	when -1 then "2:#{letter * s2.count(letter)}"
  	end
  end
  letters.sort_by {|string| [-string.length, string]}.join('/')
end<file_sep>/ASCII Games : Warning: Ice! - 3kyu (#puzzles #games #ascii #character_encodings #formats)/README.md
CodeWars Kata "ASCII Games: Warning: Ice!"
Kata link : https://www.codewars.com/kata/58f4cc4e43251b1be6000082
Kata author : https://www.codewars.com/users/Voile

ASCII Games is a series of hard game-based katas revolving around the classic games we love that operates on a rectangular grid.

Any youngster Joeys should probably know what this image means, and why it is traumatic:
(Image from Bulbapedia)

In many grid-based 2D puzzle games, there is a typical form of puzzle which are usually referred to as 'ice puzzle':

    You have to traverse from point A to point B
    You can move towards one of the 4 orthogonal directions, 1 tile at a time
    Some of the floors are slippery; if you walk onto a slippery tile, you'll keep sliding in the direction you're going until you land on a non-slippery tile, or you collide with an obstacle/wall

For example, the top-left part of the above puzzle has such a solution:

You will be given an M x N well-formed rectanglar ASCII map of the form:

var map = '\
    x \n\
  #   \n\
   E  \n\
 #    \n\
    # \n\
S    #';
/*
Player starts at the start, and ends by reaching the end.

legend:
S: start (slippery, only 1 exists)
E: end (non-slippery, only 1 exists)
 : slippery tile
x: non-slippery tile
#: obstacles
(You can't go past map edges, which serves as the walls of the puzzle.)
*/

Your solver should find the optimal solution (minimal number of moves, as in, the amount of times you make a step), and return an array of directions: 'u', 'd', 'l', 'r' for up/down/left/right respectively. So for the example map above, you should return ['u', 'r', 'd', 'l', 'u', 'r']. If there are multiple solutions with the same amount of steps, tiebreak by least distance traversed. If there are still ties, just return any one of them.

Also, you might be passed some maps which does not admit any solutions. In this case, return null.
<file_sep>/Bloxorz Solver - 3kyu (#Algorithms#Games#Puzzles)/README.md
Code Wars Kata "Bloxorz Solver"
Kata link : https://www.codewars.com/kata/5a2a597a8882f392020005e5
Kata author : https://www.codewars.com/users/docgunthrop

This kata is inspired by Bloxorz, a flash-based 3D puzzle game where the objective is to maneuver a block to have it fall through a square hole.
Objective

Your goal is to maneuver a rectangular cuboid with dimensions 1 x 1 x 2 on a 2-dimensional grid made up of 1 x 1 square tiles. While moving the cuboid around, your block must never, at any point, have any part of its bottom-facing surface exposed to open air.
Input

Your function will receive an array of strings describing the layout of the grid to be traversed. A 1 represents solid ground (tiles), a 0 represents open air, a B represents your starting position, and an X represents the square hole (destination).
Output

Your function must return a string representing the minimum sequence of moves required to get the block into the square hole. It will consist of a combination of the following characters: U (up), D (down), L (left), R (right).
Block Movement

The block can cover either one or two tiles with each movement, depending on whether it is standing upright or on its long end. The image above shows an overhead view; the yellow squares represent the tiles occupied by the block and the green squares represent the tiles occupied when moved toward a given cardinal direction.

In Fig. 1, the block's position is standing upright, and in Fig. 2, the block is on its long end.
Test Example

let level1 = ['1110000000',
              '1B11110000',
              '1111111110',
              '0111111111',
              '0000011X11',
              '0000001110'];

bloxSolver(level1); //'RRDRRRD' or 'RDDRRDR'

An overhead view of the game grid for the example level1 is shown below, with a green square representing the starting position of the block, the red square representing the square hole, the light grey squares representing the platform tiles, and the dark grey areas representing open air:

grid layout of level1

Below is the sequence of moves to solve this map, numbered and highlighted in blue.

sequence of moves for level1

and another possible solution:

alternative sequence of moves for level1
Technical Details

    Input will always be valid and there will always be a solution.
    The block always begins in an upright position.
    The maximum grid size will be 15 x 20 (rows x colums)

If you enjoyed this kata, be sure to check out my other katas.<file_sep>/Range Extraction - 4kyu (#algorithms #formatting)/range_extraction.rb
def solution(list)
  new_arr = []
  sub_arr = []
  i = 0
  list.length.times do
    if list[i + 1] == list[i] + 1
      sub_arr.push(list[i])
    else
      sub_arr.push(list[i])
      case sub_arr.size
      when 1
        new_arr.push(sub_arr[0])
      when 2
        new_arr.push(sub_arr[0])
        new_arr.push(sub_arr[1])
      else
        new_arr.push(sub_arr)
      end
      sub_arr = []
    end
    i+=1
  end
  new_arr.map! do |e|
    if e.is_a? Integer
      e.to_s
    else
      e[0].to_s + "-" + e[-1].to_s
    end
  end
  new_arr.join(',')
end<file_sep>/Number of Proper Fractions with Denominator d - 4kyu (#fundamentals #mathematics)/proper_fraction.rb
require 'prime'
def proper_fractions(n)
  n <= 1 ? 0 : Prime.prime_division(n).map { |e| e.first**e.last - e.first**(e.last-1) }.reduce(:*)
end<file_sep>/Path FInder #3: The Alpinist - 3kyu (#algorithms)/README.md
CodeWars Kata "Path Finder #3: The Alpinist"
Kata link : https://www.codewars.com/kata/576986639772456f6f00030c
Kata author : https://www.codewars.com/users/evk

You are at start location [0, 0] in mountain area of NxN and you can only move in one of the four cardinal directions (i.e. North, East, South, West). Return minimal number of climb rounds to target location [N-1, N-1]. Number of climb rounds between adjacent locations is defined as difference of location altitudes (ascending or descending).

Location altitude is defined as an integer number (0-9).<file_sep>/Recover secret string from random triplet - 4kyu (#algorithms)/recover_string.js
var recoverSecret = function(triplets) {
  function flatten(a) { return a.reduce((a,b)=> a.concat(Array.isArray(b) ? flatten(b) : b), [])};
  var lettersProv = flatten(triplets);
  var letters = []
  for (let i = 0; i < lettersProv.length; i++) {
    if (!letters.includes(lettersProv[i])) { letters.push(lettersProv[i]) }
  }
  for (let i = 0; i < triplets.length; i++){
    for (let j = 0; j < triplets[i].length-1; j++) {
      if (letters.indexOf(triplets[i][j]) < letters.indexOf(triplets[i][j+1])) {
        letters.splice(letters.indexOf(triplets[i][j+1]), 1);
        letters.splice(letters.indexOf(triplets[i][j]), 0, triplets[i][j+1]);
      }
    }
  }
  var str = ""
  for (let i = letters.length-1; i >= 0; i--){
    str += letters[i];
  }
  return str;
}

languages: Markdown JavaScript Ruby Python

repo_language: Markdown

repo_name: VictorFouquet/Code-Wars-Katas


text:
<repo_name>linclin/docker-alpine-nginx-php7<file_sep>/Dockerfile
#sudo docker build -t alpine-nginx-php7 .
#sudo docker run --name alpine-nginx-php7   -d   alpine-nginx-php7
FROM alpine:3.6

RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g' /etc/apk/repositories && \
    apk update && \
    apk add nginx bash tzdata ca-certificates s6 curl ssmtp php7 php7-phar php7-curl \
    php7-fpm php7-json php7-zlib php7-xml php7-dom php7-ctype php7-opcache php7-zip php7-iconv \
    php7-pdo php7-pdo_mysql php7-pdo_sqlite php7-pdo_pgsql php7-mbstring php7-session \
    php7-gd php7-mcrypt php7-openssl php7-sockets php7-posix php7-ldap php7-simplexml && \
    echo "Asia/Shanghai" > /etc/timezone && \
    cp -r -f /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
    rm -rf /var/cache/apk/*   /tmp/*     && \
    rm -f /etc/php7/php-fpm.d/www.conf && \
    touch /etc/php7/php-fpm.d/env.conf

RUN curl -sS https://getcomposer.org/installer | php -- --filename=/usr/local/bin/composer

RUN rm -rf /var/www/* && mkdir /var/www/app

COPY files/php/conf.d/local.ini /etc/php7/conf.d/
COPY files/php/php-fpm.conf /etc/php7/
COPY files/php/phpinfo.php /var/www/app/index.php
COPY files/nginx/nginx.conf /etc/nginx/nginx.conf
COPY files/services.d /etc/services.d

EXPOSE 80

ENTRYPOINT ["/bin/s6-svscan", "/etc/services.d"]
CMD []

repo_language: Dockerfile


text:
<file_sep>package main

import "fmt"

func (cli *CLI) createBlockchain(address, nodeID string) {
	bc := CreateBlockchain(address, nodeID)
	defer bc.db.Close()

	UTXOSet := UTXOSet{bc}
	UTXOSet.Reindex()

	fmt.Println("Blockchain created!")
}
<file_sep># golang-blockchain
<file_sep>package main

import (
	"fmt"
	"log"
)

func (cli *CLI) startNode(nodeID, minerAddress string) {
	fmt.Printf("Starting node %s\n", nodeID)
	if len(minerAddress) > 0 {
		if ValidateAddress(minerAddress) {
			fmt.Printf("Mining... Rewards will be sent to %s\n", minerAddress)
		} else {
			log.Panic("Invalid miner address")
		}
	}

	StartServer(nodeID, minerAddress)
}

languages: Markdown Go


text:
<file_sep># alura-barbearia
Desenvolvimento de pagina WEB, para as aulas de HTML e CSS do curso Alura.

branch_name: refs/heads/main

repo_name: GustavoTeofilo/alura-barbearia