Skip to content

Instantly share code, notes, and snippets.

@chriseidhof
Created October 27, 2016 10:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save chriseidhof/b0fb6b0a4cf370e873dc56ee0a6ad42d to your computer and use it in GitHub Desktop.
Save chriseidhof/b0fb6b0a4cf370e873dc56ee0a6ad42d to your computer and use it in GitHub Desktop.
enum Block {
case code(code: String)
case text(String)
case header(String)
}
enum PlaygroundElement {
case code(String)
case documentation([Block])
}
func playground(blocks: [Block]) -> [PlaygroundElement] {
// We want to generate a playground from an array of `Block` elements.
//
// Separate the code from the documentation.
// All the consecutive non-code should be grouped together.
}
// The following input:
let sample: [Block] = [.code("swift sample code"), .header("My Header"), .text("Hello"), .code("more"), .text("text")]
// Should return the following result:
let result: [PlaygroundElement] = [
.code("swift sample code"),
.documentation[.header("My Header"), .text("Hello")]
.code("more"),
.documentation[.text("text")]
]
@brunogb
Copy link

brunogb commented Nov 4, 2016

Using indirectEnums and also without mutating the original structs

import Foundation

enum Block {
    case code(String)
    case text(String)
    case header(String)
}

enum PlaygroundElement {
    case code(String)
    case documentation([Block])
}

indirect enum PlaygroundBlock {
    case code(String, PlaygroundBlock?)
    case documentation([Block], PlaygroundBlock?)
    
    init(block: Block, parent: PlaygroundBlock? = nil) {
        switch block {
        case let .code(value):
            self = .code(value, parent)
        default:
            self = .documentation([block], parent)
        }
    }
    
    mutating func process(block: Block)-> PlaygroundBlock {
        switch (self, block) {
        case (.code, _):
            return PlaygroundBlock(block: block, parent: self)
        case (.documentation, .code):
            return PlaygroundBlock(block: block, parent: self)
        case (.documentation(let (values, parent)), _):
            var newValues = [block]
            newValues.append(contentsOf: values)
            self = .documentation(newValues, parent)
            return self
        }
    }
    
    func flatMap()-> [PlaygroundElement] {
        switch self {
        case let .code(value, parent):
            var items: [PlaygroundElement] = [.code(value)]
            if let parent = parent {
                items.append(contentsOf: parent.flatMap())
            }
            return items
        case let .documentation(values, parent):
            var items: [PlaygroundElement] = [.documentation(values)]
            if let parent = parent {
                items.append(contentsOf: parent.flatMap())
            }
            return items
        }
    }
    
}

func playground(blocks: [Block]) -> [PlaygroundElement] {
    var consumableBlocks: [Block] = blocks
    guard let lastBlock = consumableBlocks.popLast() else { return [] }
    var lastLine = PlaygroundBlock(block: lastBlock)
    while let nextBlock = consumableBlocks.popLast() {
        lastLine = lastLine.process(block: nextBlock)
    }
    return lastLine.flatMap()
}

let sample: [Block] = [.code("swift sample code"), .header("My Header"), .text("Hello"), .code("more"), .text("text")]
let results = playground(blocks: sample)
results.count == 4
print(results)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment