Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Talk #1

Open
clsource opened this issue Nov 26, 2020 · 19 comments
Open

Talk #1

clsource opened this issue Nov 26, 2020 · 19 comments

Comments

@clsource
Copy link
Contributor

Hello,
@PureFox48
I have made this repository to archive the Rosetta Wren code.

Please, would you kindly provide a zip file (attached here) with all the modules and code available so far?. If that's not possible it's ok and I will extract the data directly from Rosseta's page.

I would greatly appreciate it if you could update this issue whenever is possible to update the files.

Thank you very much for your kindness and awesome labor at creating Wren examples and code.

@PureFox48
Copy link

That's brilliant! Many thanks for creating this repo.

I've made changes to 6 modules in recent days, namely:

Wren-big
Wren-complex
Wren-fmt
Wren-matrix
Wren-math
Wren-set

The changes include the addition of complex matrices, formatting support for complex numbers and a bag class.

I wonder if I could ask you to update these six modules directly from the RC source code.

The existing modules are now feature complete and I've no plans to change any of them again unless bugs surface. So hopefully these will be the last changes for a while apart, of course, from adding new modules to the collection.

Thanks again for your efforts here.

@clsource
Copy link
Contributor Author

clsource commented Nov 29, 2020

Ok updated the 777 files so far 👍
8f2860f

@PureFox48
Copy link

PureFox48 commented Nov 29, 2020

Wow, I hadn't realized that you intended to upload the code for all the RC tasks to the repo as well as the library modules!

That's great but it does give us some problems:

  1. One of the modules (set.wren) has the same name as a task. That has resulted in the latter over-writing the former.

    There's also another task, UPC (to do with bar codes) which I haven't tackled yet but will have the same name as the module upc.wren which is concerned with splitting strings up into 'user perceived characters'.

    I think the best solution to this is to keep the library modules in a separate sub-directory from the tasks which is how you had it originally.

  2. I haven't in fact written the code for all 777 tasks. There were 16 tasks written by others before I started though I have altered some of them for various reasons and added syntax highlighting to them all.

    The first 3 of these tasks are:

    Hello world/text
    99 Bottles of Beer
    Hello world/Newline omission

    These were written by Edsrzf in 2015 (who created the RC's Wren category in the first place) and updated by 4d47 in 2016. I've had no hand in them at all. Neither of these users have had any involvement with RC since then.

    The next 6 tasks were written entirely by a user called Fusta in 2016:

    Apply a callback to an array
    Arrays
    Averages/Arithmetic mean
    Averages/mode
    Collections
    String length

    And finally these 7 tasks were written by Fusta in 2016 but altered by myself in 2020:

    100 doors (both versions)
    A+B
    Ackermann function
    Anonymous recursion
    Arithmetic/integer
    Array concatenation
    Array length

    Fusta has had no involvement in RC since 2017.

    This means, of course, that the code contributed by these 3 users is still subject to the RC license. It seems to me that there are 3 possible solutions to this impasse:

    (a) We exclude these tasks from the repo which would be unfortunate as the list is otherwise complete and there's very little code in any of them.

    (b) We try to contact these users to ask whether they would be prepared to place their contributions under the MIT License. I can leave a message on their user pages, if you like, but I don't know any of these people and we'll be lucky to get a reply given they haven't been involved with RC for some years.

    (c) We leave these tasks under the RC license and give the authors due credit in the headings.

    Perhaps you could let me know which of these options you prefer - personally, I'm tending towards (c).

    The remaining 761 tasks and the 16 library modules have all been written entirely by myself and (AFAIK) have not been altered by anybody else.

  3. In 38 of the tasks I've written I've made use of external libraries, viz:

    DOME for 31 tasks.
    Wren-json for 2 tasks.
    WrenGo for 5 tasks.

    All of these are hosted on Github and, luckily, are subject to the MIT license. However, I think you will agree that the relevant tasks should reference them in some way.

Incidentally, I tend to make contributions to RC most days (I'm going to add a couple more tasks after I've posted this) so it's not going to be easy to keep track of task changes but I will make a note of what I do (and anyone else does) from now on and perhaps we can update periodically.

@clsource
Copy link
Contributor Author

Ok I added the additional contributors and all affected files changed the license to FDL 1.2
I think the tasks that use DOME, json and WrenGo should refer to them inside a comment (since it would be more flexible if other external tools are used).
👍

@PureFox48
Copy link

Sorry that I managed to mess up the list of 7 cases originally authored by Fusta which I later changed though I've corrected it now.

I've been through the affected cases and the following will need correction some time to keep the license position in order:

Apply a callback to an array - wrtten solely by Fusta.
String length - both code examples were written solely by Fusta
A+B (called abb.wren) - co-authored by Fusta and myself
Anonymous recursion - ditto
Arithmetic/Integer - ditto

I agree that where external libraries have been used we should just refer to them in a comment. For the WrenGo cases, it might suffice to do nothing further because the Go 'import' statement makes it clear where the code is coming from.

Other than that, I think things should now be as accurate as we can get them.

Incidentally, I've noticed that the script seems to be skipping the odd task. I've only looked at the first few letters but Benford's Law, Bitmap/Bresenham's line algorithm and Catalan numbers/Pascal's triangle are missing. The cases are listed in snippets.log though they don't appear for some reason in snippets.makefile. Perhaps you could check this out.

Many thanks again for your efforts :)

@clsource
Copy link
Contributor Author

Ok added the proper licenses and missing files (maybe with the ' character the fetcher went nuts xd).

@clsource
Copy link
Contributor Author

@PureFox48 I have been testing out Wren Go and it seems like a good way of implementing custom functions to the Wren interpreter. Don't know if it would be a good idea creating a custom "Wren CLI" with Wren Go and use it for things outside the limits of Wren CLI.

What do you think?

Example
main.go

package main

import (
	"fmt"
	"io/ioutil"

	wren "github.com/crazyinfin8/WrenGo"
)

func main() {
	vm := wren.NewVM()
	vm.SetModule("main", wren.NewModule(wren.ClassMap{
		"MyClass": wren.NewClass(nil, nil, wren.MethodMap{
			"static sayHello()": func(vm *wren.VM, parameters []interface{}) (interface{}, error) {
				println("Hello from MyClass but from Go")
				return nil, nil
			},
		}),
	}))
	content, err := ioutil.ReadFile("main.wren")
	if err != nil {
	}

	fmt.Println(string(content))
	vm.InterpretString("main", string(content))
}

main.wren

foreign class MyClass {
    foreign static sayHello()
}

MyClass.sayHello()

@PureFox48
Copy link

Thanks for fixing those problems. It' s probably the presence of the apostrophe that was causing those files to be missed as you surmised.

With regard to WrenGo I think it would be feasible to create a custom Wren-CLI with it though it would be a lot of work. The advantage, of course, is that you'd be able to get rid of libuv and use the cross-platform Go standard libraries for file, network, crypto, regex etc. though all these would need to be suitably wrapped so you could use them from Wren.

Although I'm a big admirer of Go there are some drawbacks to using it for this kind of work. Whilst it compiles much faster than C/C++, execution speed is not as good - about on a par with the JVM and .NET languages in my experience. Also the runtime is large as it needs to deal with stuff such as garbage collection and co-routines. Consequently executables are large too.

However, a bigger concern is WrenGo itself which has a number of issues which I've filed on the repo but have yet to receive a reply. The most serious issue is that it only deals with float32 rather than float64 at present. I think this must be an oversight by the author as I can't think of any obvious reason why this should be so.

Anyway the author's commitment to the repo and keeping it up to date has to be in doubt.

Having said that, it was the only one of the 3 (?) Wren/Go binders which was up to date and I could get to work. Although I've only used embedding when absolutely necessary on RC (nobody on there wants to be bothered to compile a host program as well as the Wren code!), it's worked fine when I've used it though I think I used C instead on the last one I did.

On balance, I think it's better to wait and see what Wren-CLI 0.4.0 has to offer (and intends to offer in future) before embarking on a project such as this.

@clsource
Copy link
Contributor Author

clsource commented Dec 1, 2020

Thanks. Yes for this use case is best to rely on WrenCLI and Vanilla Wren Go.

@PureFox48
Copy link

I'm pleased to say that my reservations about WrenGo were premature as the author has now responded to the issues and fixed a couple of things including the float64 bug. Better still, the whole repo has been updated to Wren 0.4.0- Pre so I'm happy now that it's a viable vehicle for embedding Wren in a Go application. Will be using it more on RC in future :)

@clsource
Copy link
Contributor Author

@PureFox48 it seems tau value is wrong https://tauday.com/

it should be 2 times PI

https://rosettacode.org/mw/index.php?title=Category_talk:Wren-math&action=edit&section=1

    static tau  { 1.6180339887498948482  } // synonym for phi

@PureFox48
Copy link

It's not actually wrong. It's just a different usage of the tau symbol to mean the golden ratio rather than 2 * pi. However, phi is used more often these days for the former and now we have Num.tau in the standard library as well, I'm going to remove Math.tau from math.wren to avoid any confusion.

I'll need to check the various modules to see if there is anything else we can remove because it's now been implemented in Wren 0.4.0.

I've added a lot of stuff to RC since we last spoke about this and we're now up to 1,104 tasks completed. Three more modules have been added - dynamic, ioutil and long - and I've fixed minor bugs and added new features to some of the existing ones as well.

When Wren-cli 0.4.0 is eventually released (I upgraded to the latest build earlier today), it might be an idea to run your script again to upload the latest versions of everything to keep the two sites synchronized.

@clsource
Copy link
Contributor Author

Understood 👍

Quick question. Do you have a zip file with all your code?. You can upload it here as a comment and it would make the update process more easy and quickly.

In another comment I'm working on a playground app (and including your libs) to quickly working with Wren and having real time feedback.

https://github.com/NinjasCL/wren-playground

💯

@PureFox48
Copy link

Do you have a zip file with all your code?

I'm afraid I don't and it would very difficult to make one from the files I have on my machine.

When I started adding Wren snippets to RC, I didn't think they'd have any permanent value to anyone (even myself) and so I've made no attempt to synchronize what's on RC with what's on my machine.

The file names will usually be different (I'm lazy so prefer short names), I may have written several solutions for the same task and only posted one of them, I may have edited the RC file direct and not bothered to update my local version and so forth.

The only exception to this is the 19 modules where it's important to keep the two copies synchronized.

I wonder whether, given the 'shifting sands', the aims of this repo are too ambitious and we should just archive (or even remove altogether) the task solutions and concentrate on the modules?

I don't often make changes to the latter and, when I do, I could change the file on the repo at the same time - you wouldn't need to do anything in this regard. As long as the module file contains a link back to its RC page, there will be plenty of examples listed for those interested to get their teeth into. They can simply copy and paste the code for an example from RC.

Your Wren-playground looks promising. Are you thinking of supporting DOME stuff as well in that?

@clsource
Copy link
Contributor Author

clsource commented Dec 5, 2024

Hello @PureFox48

Your Wren-playground looks promising. Are you thinking of supporting DOME stuff as well in that?

I don't think so, supporting DOME would require more sophisticated code, as an IDE maybe.

I notice that there is this task: https://rosettacode.org/wiki/Nonogram_solver#Wren

But I could not find the inverse case, where you have a solved Nonogram and you must show the numbers to solve it.

Example

. # # # . . . .
# # . # . . . .
. # # # . . # #
. . # # . . # #
. . # # # # # #
# . # # # # # .
# # # # # # . .
. . . . # . . .
. . . # # . . .

Solution

["C BA CB BB F AE F A B", "AB CA AE GA E C D C"]

I searched in Rosetta and is not found there.

Would be this be difficult to solve?
Thanks 💯

@clsource
Copy link
Contributor Author

clsource commented Dec 5, 2024

I more or less modified the code but have weird results in big nonograms

// from https://rosettacode.org/wiki/Nonogram_solver#Wren
import "./pattern" for Pattern
import "./math" for Nums, Boolean

var p = Pattern.new("/s")

var genSequence // recursive
genSequence = Fn.new { |ones, numZeros|
    if (ones.isEmpty) return ["0" * numZeros]
    var result = []
    var x = 1
    while (x < numZeros - ones.count + 2) {
        var skipOne = ones.skip(1).toList
        for (tail in genSequence.call(skipOne, numZeros - x)) {
            result.add("0" * x + ones[0] + tail)
        }
        x = x + 1
    }
    return result
}

/* If all the candidates for a row have a value in common for a certain cell,
    then it's the only possible outcome, and all the candidates from the
    corresponding column need to have that value for that cell too. The ones
    that don't, are removed. The same for all columns. It goes back and forth,
    until no more candidates can be removed or a list is empty (failure).
*/
var reduce =  Fn.new { |a, b|
    var countRemoved = 0
    for (i in 0...a.count) {
        var commonOn  = List.filled(b.count, true)
        var commonOff = List.filled(b.count, false)

        // determine which values all candidates of a[i] have in common
        for (candidate in a[i]) {
            for (i in 0...b.count) {
                commonOn[i]  = Boolean.and(commonOn[i], candidate[i])
                commonOff[i] = Boolean.or(commonOff[i], candidate[i])
            }
        }

        // remove from b[j] all candidates that don't share the forced values
        for (j in 0...b.count) {
            var fi = i
            var fj = j
            var removals = false
            b[j].each { |cnd|
                if ((commonOn[fj] && !cnd[fi]) || (!commonOff[fj] && cnd[fi])) {
                    b[j].remove(cnd)
                    removals = true
                }
            }
            if (removals) countRemoved = countRemoved + 1
            if (b[j].isEmpty) return -1
        }
    }
    return countRemoved
}

var reduceMutual = Fn.new { |cols, rows|
    var countRemoved1 = reduce.call(cols, rows)
    if (countRemoved1 == -1) return -1
    var countRemoved2 = reduce.call(rows, cols)
    if (countRemoved2 == -1) return -1
    return countRemoved1 + countRemoved2
}

// collect all possible solutions for the given clues
var getCandidates = Fn.new { |data, len|
    var result = []
    for (s in data) {
        var lst = []
        var a = s.bytes
        var sumChars = Nums.sum(a.map { |b| b - 64 })
        var prep = a.map { |b| "1" * (b - 64) }.toList

        for (r in genSequence.call(prep, len - sumChars + 1)) {
            var bits = r[1..-1].bytes
            var len = bits.count
            if (len % 64 != 0) len = (len/64).ceil * 64
            var bitset = List.filled(len, false)
            for (i in 0...bits.count.min(bitset.count)) bitset[i] = bits[i] == 49
            lst.add(bitset)
        }
        result.add(lst)
    }
    return result
}

var lettersToNumbers = Fn.new{|data|
    var result = []
    for (s in data) {
        result.add(s.bytes.map{|char| char - 64}.toList)
    }

    return result
}

var newPuzzle = Fn.new { |data|
    var rowData = p.splitAll(data[0])
    var colData = p.splitAll(data[1])
    var rows_numbers = lettersToNumbers.call(rowData)
    var cols_numbers = lettersToNumbers.call(colData)

    var rows = getCandidates.call(rowData, colData.count)
    
    var cols = getCandidates.call(colData, rowData.count)

    while (true) {
        var numChanged = reduceMutual.call(cols, rows)
        if (numChanged == -1) {
            System.print("No solution")
            return
        }
        if (numChanged <= 0) break
    }

    var count = 0
    for (row in rows) {
        for (i in 0...cols.count) {
            System.write(row[0][i] ? "■ " : ". ")
        }
        
        // Print Rows
        for (number in rows_numbers[count]) {
            System.write(number.toString + " ")
        }

        System.print()
        count = count + 1
    }

    var max_rows = rows.count 
    var max_cols = 0
    for(col in cols_numbers) {
        if (col.count >= max_cols) {
            max_cols = col.count
        }
    }

    for(index in 0...max_cols) {
        for(col in cols_numbers) {
            count = count + 1
            if (index < col.count) {
                System.write(col[index].toString + " ")
            }

        }
        System.print()
    }

}

/*
// Example

var p1 = ["C BA CB BB F AE F A B", "AB CA AE GA E C D C"]

var p2 = [
    "F CAC ACAC CN AAA AABB EBB EAA ECCC HCCC",
    "D D AE CD AE A DA BBB CC AAB BAA AAB DA AAB AAA BAB AAA CD BBA DA"
]

var p3 = [
    "CA BDA ACC BD CCAC CBBAC BBBBB BAABAA ABAD AABB BBH " +
    "BBBD ABBAAA CCEA AACAAB BCACC ACBH DCH ADBE ADBB DBE ECE DAA DB CC",
    "BC CAC CBAB BDD CDBDE BEBDF ADCDFA DCCFB DBCFC ABDBA BBF AAF BADB DBF " +
    "AAAAD BDG CEF CBDB BBB FC"
]

var p4 = [
    "E BCB BEA BH BEK AABAF ABAC BAA BFB OD JH BADCF Q Q R AN AAN EI H G",
    "E CB BAB AAA AAA AC BB ACC ACCA AGB AIA AJ AJ " +
    "ACE AH BAF CAG DAG FAH FJ GJ ADK ABK BL CM"
]


for (puzzleData in [p1, p2, p3, p4]) newPuzzle.call(puzzleData)

*/
. ■ ■ ■ . . . . 3
■ ■ . ■ . . . . 2 1
. ■ ■ ■ . . ■ ■ 3 2
. . ■ ■ . . ■ ■ 2 2
. . ■ ■ ■ ■ ■ ■ 6
■ . ■ ■ ■ ■ ■ . 1 5
■ ■ ■ ■ ■ ■ . . 6
. . . . ■ . . . 1
. . . ■ ■ . . . 2
1 3 1 7 5 3 4 3
2 1 5 1
. . . . . . . . . . ■ ■ ■ ■ ■ ■ . . . . 6
. . . . . . . . ■ ■ ■ . ■ . . ■ ■ ■ . . 3 1 3
. . . ■ . . ■ ■ ■ . . . ■ . . . . ■ ■ ■ 1 3 1 3
. . ■ ■ ■ . ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ 3 14
. . . ■ . . ■ . . . . . . . . . . . . ■ 1 1 1
. . ■ . ■ . ■ ■ . . . . . . . . . . ■ ■ 1 1 2 2
■ ■ ■ ■ ■ . . ■ ■ . . . . . . . . ■ ■ . 5 2 2
■ ■ ■ ■ ■ . . . ■ . . . . . . . . ■ . . 5 1 1
■ ■ ■ ■ ■ . . ■ ■ ■ . ■ ■ ■ . ■ ■ ■ . . 5 3 3 3
■ ■ ■ ■ ■ ■ ■ ■ . ■ ■ ■ . ■ ■ ■ . ■ ■ ■ 8 3 3 3
4 4 1 3 1 1 4 2 3 1 2 1 4 1 1 2 1 3 2 4
5 4 5 1 2 3 1 1 1 1 1 1 1 1 4 2 1
2 2 1 2 2 1 2 1 1
. . . . ■ ■ ■ . ■ . . . . . . . . . . . 3 1
. . . . ■ ■ . ■ ■ ■ ■ . ■ . . . . . . . 2 4 1
. . . . ■ . ■ ■ ■ . ■ ■ ■ . . . . . . . 1 3 3
. . ■ ■ . ■ ■ ■ ■ . . . . . . . . . . . 2 4
. ■ ■ ■ . ■ ■ ■ . ■ . . . . ■ ■ ■ . . . 3 3 1 3
■ ■ ■ . . ■ ■ . ■ ■ . . . ■ . ■ ■ ■ . . 3 2 2 1 3
■ ■ . . ■ ■ . ■ ■ . . . . ■ ■ . ■ ■ . . 2 2 2 2 2
. . . . ■ ■ . ■ . ■ . . ■ ■ . ■ . ■ . . 2 1 1 2 1 1
. . . . ■ . ■ ■ . ■ . . . ■ ■ ■ ■ . . . 1 2 1 4
. . . . ■ . ■ . ■ ■ . . . . . ■ ■ . . . 1 1 2 2
. . . . . ■ ■ . ■ ■ . . ■ ■ ■ ■ ■ ■ ■ ■ 2 2 8
. . . . ■ ■ . ■ ■ . . . ■ ■ . . ■ ■ ■ ■ 2 2 2 4
. . . . ■ . ■ ■ . ■ ■ . ■ . . . ■ . . ■ 1 2 2 1 1 1
■ ■ ■ . . ■ ■ ■ . ■ ■ ■ ■ ■ . . . . . ■ 3 3 5 1
■ . ■ . ■ ■ ■ . ■ . . . . ■ . . . . ■ ■ 1 1 3 1 1 2
■ ■ . . ■ ■ ■ . ■ . . . . ■ ■ ■ . ■ ■ ■ 2 3 1 3 3
. ■ . ■ ■ ■ . ■ ■ . ■ ■ ■ ■ ■ ■ ■ ■ . . 1 3 2 8
. ■ ■ ■ ■ . ■ ■ ■ . ■ ■ ■ ■ ■ ■ ■ ■ . . 4 3 8
. . . ■ . ■ ■ ■ ■ . ■ ■ . ■ ■ ■ ■ ■ . . 1 4 2 5
. . . ■ . ■ ■ ■ ■ . ■ ■ . . . ■ ■ . . . 1 4 2 2
. . . . ■ ■ ■ ■ . . ■ ■ . . . ■ ■ ■ ■ ■ 4 2 5
. . . ■ ■ ■ ■ ■ . ■ ■ ■ . . . ■ ■ ■ ■ ■ 5 3 5
. . . ■ ■ ■ ■ . ■ . . . . . . . . . . ■ 4 1 1
. . ■ ■ ■ ■ . ■ ■ . . . . . . . . . . . 4 2
. . ■ ■ ■ . ■ ■ ■ . . . . . . . . . . . 3 3
2 3 3 2 3 2 1 4 4 1 2 1 2 4 1 2 3 3 2 6
3 1 2 4 4 5 4 3 2 2 2 1 1 2 1 4 5 2 2 3
3 1 4 2 2 3 3 3 4 6 6 4 6 1 7 6 4 2
2 4 4 4 6 6 2 2 1 2
5 6 6 2 3 1 4
1
. . . . . . . . . . . . . . . . . . . . ■ ■ ■ ■ ■ 5
. . ■ ■ . . . . . . . . . . . . . . ■ ■ ■ . . ■ ■ 2 3 2
. ■ ■ . . . . . . . . . . . . . . ■ ■ ■ ■ ■ . . ■ 2 5 1
■ ■ . . . . . . . . . . . . . ■ ■ ■ ■ ■ ■ ■ ■ . . 2 8
■ ■ . . . . ■ ■ ■ ■ ■ . ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ . . 2 5 11
■ . ■ . . ■ ■ . . . . ■ . . . . ■ ■ ■ ■ ■ ■ . . . 1 1 2 1 6
■ . . ■ ■ . . . . . ■ . . . . . . . ■ ■ ■ . . . . 1 2 1 3
■ ■ . . . . . . . . ■ . . . . . . . . . . . . . ■ 2 1 1
. ■ ■ . . . . . ■ ■ ■ ■ ■ ■ . . . . . . . . . ■ ■ 2 6 2
. . ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ . . . . ■ ■ ■ ■ 15 4
. . . . . ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ . . ■ ■ ■ ■ ■ ■ ■ ■ 10 8
. . . . ■ ■ . ■ . ■ ■ ■ ■ . ■ ■ ■ . . ■ ■ ■ ■ ■ ■ 2 1 4 3 6
. . . . . . . . ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ 17
. . . . . . . . ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ 17
. . . . . . . ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ 18
. . . . . . . ■ . . . ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ 1 14
. . . . . . . ■ . ■ . ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ 1 1 14
. . . . . . . . ■ ■ ■ ■ ■ . . . ■ ■ ■ ■ ■ ■ ■ ■ ■ 5 9
. . . . . . . . . . . . . . . . . ■ ■ ■ ■ ■ ■ ■ ■ 8
. . . . . . . . . . . . . . . . . . ■ ■ ■ ■ ■ ■ ■ 7
5 3 2 1 1 1 2 1 1 1 1 1 1 1 1 2 3 4 6 6 7 1 1 2 3
2 1 1 1 3 2 3 3 7 9 10 10 3 8 1 1 1 1 10 10 4 2 12 13
2 1 1 3 3 2 1 5 6 7 7 8 11 11
1

@PureFox48
Copy link

I can't say I remember much about that particular task but, if you want to round-trip the results, this seems to be working OK. Note that I've imported fmt.wren to get the column counts to line up properly.

import "./pattern" for Pattern
import "./math" for Nums, Boolean
import "./fmt" for Fmt

var p = Pattern.new("/s")

var genSequence // recursive
genSequence = Fn.new { |ones, numZeros|
    if (ones.isEmpty) return ["0" * numZeros]
    var result = []
    var x = 1
    while (x < numZeros - ones.count + 2) {
        var skipOne = ones.skip(1).toList
        for (tail in genSequence.call(skipOne, numZeros - x)) {
            result.add("0" * x + ones[0] + tail)
        }
        x = x + 1
    }
    return result
}

/* If all the candidates for a row have a value in common for a certain cell,
    then it's the only possible outcome, and all the candidates from the
    corresponding column need to have that value for that cell too. The ones
    that don't, are removed. The same for all columns. It goes back and forth,
    until no more candidates can be removed or a list is empty (failure).
*/
var reduce =  Fn.new { |a, b|
    var countRemoved = 0
    for (i in 0...a.count) {
        var commonOn  = List.filled(b.count, true)
        var commonOff = List.filled(b.count, false)

        // determine which values all candidates of a[i] have in common
        for (candidate in a[i]) {
            for (i in 0...b.count) {
                commonOn[i]  = Boolean.and(commonOn[i], candidate[i])
                commonOff[i] = Boolean.or(commonOff[i], candidate[i])
            }
        }

        // remove from b[j] all candidates that don't share the forced values
        for (j in 0...b.count) {
            var fi = i
            var fj = j
            var removals = false
            b[j].each { |cnd|
                if ((commonOn[fj] && !cnd[fi]) || (!commonOff[fj] && cnd[fi])) {
                    b[j].remove(cnd)
                    removals = true
                }
            }
            if (removals) countRemoved = countRemoved + 1
            if (b[j].isEmpty) return -1
        }
    }
    return countRemoved
}

var reduceMutual = Fn.new { |cols, rows|
    var countRemoved1 = reduce.call(cols, rows)
    if (countRemoved1 == -1) return -1
    var countRemoved2 = reduce.call(rows, cols)
    if (countRemoved2 == -1) return -1
    return countRemoved1 + countRemoved2
}

// collect all possible solutions for the given clues
var getCandidates = Fn.new { |data, len|
    var result = []
    for (s in data) {
        var lst = []
        var a = s.bytes
        var sumChars = Nums.sum(a.map { |b| b - 64 })
        var prep = a.map { |b| "1" * (b - 64) }.toList

        for (r in genSequence.call(prep, len - sumChars + 1)) {
            var bits = r[1..-1].bytes
            var len = bits.count
            if (len % 64 != 0) len = (len/64).ceil * 64
            var bitset = List.filled(len, false)
            for (i in 0...bits.count.min(bitset.count)) bitset[i] = bits[i] == 49
            lst.add(bitset)
        }
        result.add(lst)
    }
    return result
}

var newPuzzle = Fn.new { |data|
    var rowData = p.splitAll(data[0])
    var colData = p.splitAll(data[1])
    var rows = getCandidates.call(rowData, colData.count)
    var cols = getCandidates.call(colData, rowData.count)

    while (true) {
        var numChanged = reduceMutual.call(cols, rows)
        if (numChanged == -1) {
            System.print("No solution")
            return
        }
        if (numChanged <= 0) break
    }

    var rowCounts = []
    var colCounts = []

    for (r in 0...rows.count) {
        var rowCount = []
        var count = 0
        var row = rows[r]
        for (c in 0...cols.count) {
            if (row[0][c]) {
                count = count + 1
            } else if (count > 0) {
                rowCount.add(count)
                count = 0
            }
        }
        if (count > 0) rowCount.add(count)
        rowCounts.add(rowCount)
    }

    for (c in 0...cols.count) {
        var colCount = []
        var count = 0
        for (r in 0...rows.count) {
            var row = rows[r]
            if (row[0][c]) {
                count = count + 1
            } else if (count > 0) {
                colCount.add(count)
                count = 0
            }
        }
        if (count > 0) colCount.add(count)
        colCounts.add(colCount)
    }

    var maxColCount = 0
    for (cc in colCounts) {
        if (cc.count > maxColCount) maxColCount = cc.count
    }

    for (r in 0...rows.count) {
        var row = rows[r]
        for (c in 0...cols.count) {
            System.write(row[0][c] ? " # " : " . ")
        }
        for (rc in 0...rowCounts[r].count) {
            System.write(" %(rowCounts[r][rc])")
        }
        System.print()
    }

    for (i in 1..maxColCount) {
        for (cc in colCounts) {
            if (i <= cc.count) Fmt.write("$2d ", cc[i-1]) else System.write("   ")
        }
        System.print()
    }
    System.print()
}

var p1 = ["C BA CB BB F AE F A B", "AB CA AE GA E C D C"]

var p2 = [
    "F CAC ACAC CN AAA AABB EBB EAA ECCC HCCC",
    "D D AE CD AE A DA BBB CC AAB BAA AAB DA AAB AAA BAB AAA CD BBA DA"
]

var p3 = [
    "CA BDA ACC BD CCAC CBBAC BBBBB BAABAA ABAD AABB BBH " +
    "BBBD ABBAAA CCEA AACAAB BCACC ACBH DCH ADBE ADBB DBE ECE DAA DB CC",
    "BC CAC CBAB BDD CDBDE BEBDF ADCDFA DCCFB DBCFC ABDBA BBF AAF BADB DBF " +
    "AAAAD BDG CEF CBDB BBB FC"
]

var p4 = [
    "E BCB BEA BH BEK AABAF ABAC BAA BFB OD JH BADCF Q Q R AN AAN EI H G",
    "E CB BAB AAA AAA AC BB ACC ACCA AGB AIA AJ AJ " +
    "ACE AH BAF CAG DAG FAH FJ GJ ADK ABK BL CM"
]

for (puzzleData in [p1, p2, p3, p4]) newPuzzle.call(puzzleData)
 .  #  #  #  .  .  .  .  3
 #  #  .  #  .  .  .  .  2 1
 .  #  #  #  .  .  #  #  3 2
 .  .  #  #  .  .  #  #  2 2
 .  .  #  #  #  #  #  #  6
 #  .  #  #  #  #  #  .  1 5
 #  #  #  #  #  #  .  .  6
 .  .  .  .  #  .  .  .  1
 .  .  .  #  #  .  .  .  2
 1  3  1  7  5  3  4  3 
 2  1  5  1             

 .  .  .  .  .  .  .  .  .  .  #  #  #  #  #  #  .  .  .  .  6
 .  .  .  .  .  .  .  .  #  #  #  .  #  .  .  #  #  #  .  .  3 1 3
 .  .  .  #  .  .  #  #  #  .  .  .  #  .  .  .  .  #  #  #  1 3 1 3
 .  .  #  #  #  .  #  #  #  #  #  #  #  #  #  #  #  #  #  #  3 14
 .  .  .  #  .  .  #  .  .  .  .  .  .  .  .  .  .  .  .  #  1 1 1
 .  .  #  .  #  .  #  #  .  .  .  .  .  .  .  .  .  .  #  #  1 1 2 2
 #  #  #  #  #  .  .  #  #  .  .  .  .  .  .  .  .  #  #  .  5 2 2
 #  #  #  #  #  .  .  .  #  .  .  .  .  .  .  .  .  #  .  .  5 1 1
 #  #  #  #  #  .  .  #  #  #  .  #  #  #  .  #  #  #  .  .  5 3 3 3
 #  #  #  #  #  #  #  #  .  #  #  #  .  #  #  #  .  #  #  #  8 3 3 3
 4  4  1  3  1  1  4  2  3  1  2  1  4  1  1  2  1  3  2  4 
       5  4  5     1  2  3  1  1  1  1  1  1  1  1  4  2  1 
                      2     2  1  2     2  1  2  1     1    

 .  .  .  .  #  #  #  .  #  .  .  .  .  .  .  .  .  .  .  .  3 1
 .  .  .  .  #  #  .  #  #  #  #  .  #  .  .  .  .  .  .  .  2 4 1
 .  .  .  .  #  .  #  #  #  .  #  #  #  .  .  .  .  .  .  .  1 3 3
 .  .  #  #  .  #  #  #  #  .  .  .  .  .  .  .  .  .  .  .  2 4
 .  #  #  #  .  #  #  #  .  #  .  .  .  .  #  #  #  .  .  .  3 3 1 3
 #  #  #  .  .  #  #  .  #  #  .  .  .  #  .  #  #  #  .  .  3 2 2 1 3
 #  #  .  .  #  #  .  #  #  .  .  .  .  #  #  .  #  #  .  .  2 2 2 2 2
 .  .  .  .  #  #  .  #  .  #  .  .  #  #  .  #  .  #  .  .  2 1 1 2 1 1
 .  .  .  .  #  .  #  #  .  #  .  .  .  #  #  #  #  .  .  .  1 2 1 4
 .  .  .  .  #  .  #  .  #  #  .  .  .  .  .  #  #  .  .  .  1 1 2 2
 .  .  .  .  .  #  #  .  #  #  .  .  #  #  #  #  #  #  #  #  2 2 8
 .  .  .  .  #  #  .  #  #  .  .  .  #  #  .  .  #  #  #  #  2 2 2 4
 .  .  .  .  #  .  #  #  .  #  #  .  #  .  .  .  #  .  .  #  1 2 2 1 1 1
 #  #  #  .  .  #  #  #  .  #  #  #  #  #  .  .  .  .  .  #  3 3 5 1
 #  .  #  .  #  #  #  .  #  .  .  .  .  #  .  .  .  .  #  #  1 1 3 1 1 2
 #  #  .  .  #  #  #  .  #  .  .  .  .  #  #  #  .  #  #  #  2 3 1 3 3
 .  #  .  #  #  #  .  #  #  .  #  #  #  #  #  #  #  #  .  .  1 3 2 8
 .  #  #  #  #  .  #  #  #  .  #  #  #  #  #  #  #  #  .  .  4 3 8
 .  .  .  #  .  #  #  #  #  .  #  #  .  #  #  #  #  #  .  .  1 4 2 5
 .  .  .  #  .  #  #  #  #  .  #  #  .  .  .  #  #  .  .  .  1 4 2 2
 .  .  .  .  #  #  #  #  .  .  #  #  .  .  .  #  #  #  #  #  4 2 5
 .  .  .  #  #  #  #  #  .  #  #  #  .  .  .  #  #  #  #  #  5 3 5
 .  .  .  #  #  #  #  .  #  .  .  .  .  .  .  .  .  .  .  #  4 1 1
 .  .  #  #  #  #  .  #  #  .  .  .  .  .  .  .  .  .  .  .  4 2
 .  .  #  #  #  .  #  #  #  .  .  .  .  .  .  .  .  .  .  .  3 3
 2  3  3  2  3  2  1  4  4  1  2  1  2  4  1  2  3  3  2  6 
 3  1  2  4  4  5  4  3  2  2  2  1  1  2  1  4  5  2  2  3 
    3  1  4  2  2  3  3  3  4  6  6  4  6  1  7  6  4  2    
       2     4  4  4  6  6  2        2     1        2       
             5  6  6  2  3  1              4                
                   1                                        

 .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  #  #  #  #  #  5
 .  .  #  #  .  .  .  .  .  .  .  .  .  .  .  .  .  .  #  #  #  .  .  #  #  2 3 2
 .  #  #  .  .  .  .  .  .  .  .  .  .  .  .  .  .  #  #  #  #  #  .  .  #  2 5 1
 #  #  .  .  .  .  .  .  .  .  .  .  .  .  .  #  #  #  #  #  #  #  #  .  .  2 8
 #  #  .  .  .  .  #  #  #  #  #  .  #  #  #  #  #  #  #  #  #  #  #  .  .  2 5 11
 #  .  #  .  .  #  #  .  .  .  .  #  .  .  .  .  #  #  #  #  #  #  .  .  .  1 1 2 1 6
 #  .  .  #  #  .  .  .  .  .  #  .  .  .  .  .  .  .  #  #  #  .  .  .  .  1 2 1 3
 #  #  .  .  .  .  .  .  .  .  #  .  .  .  .  .  .  .  .  .  .  .  .  .  #  2 1 1
 .  #  #  .  .  .  .  .  #  #  #  #  #  #  .  .  .  .  .  .  .  .  .  #  #  2 6 2
 .  .  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  .  .  .  .  #  #  #  #  15 4
 .  .  .  .  .  #  #  #  #  #  #  #  #  #  #  .  .  #  #  #  #  #  #  #  #  10 8
 .  .  .  .  #  #  .  #  .  #  #  #  #  .  #  #  #  .  .  #  #  #  #  #  #  2 1 4 3 6
 .  .  .  .  .  .  .  .  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  17
 .  .  .  .  .  .  .  .  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  17
 .  .  .  .  .  .  .  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  #  18
 .  .  .  .  .  .  .  #  .  .  .  #  #  #  #  #  #  #  #  #  #  #  #  #  #  1 14
 .  .  .  .  .  .  .  #  .  #  .  #  #  #  #  #  #  #  #  #  #  #  #  #  #  1 1 14
 .  .  .  .  .  .  .  .  #  #  #  #  #  .  .  .  #  #  #  #  #  #  #  #  #  5 9
 .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  #  #  #  #  #  #  #  #  8
 .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  #  #  #  #  #  #  #  7
 5  3  2  1  1  1  2  1  1  1  1  1  1  1  1  2  3  4  6  6  7  1  1  2  3 
    2  1  1  1  3  2  3  3  7  9 10 10  3  8  1  1  1  1 10 10  4  2 12 13 
       2  1  1        3  3  2  1        5     6  7  7  8       11 11       
                         1                                                 

@clsource
Copy link
Contributor Author

clsource commented Dec 6, 2024

Thanks 💯

@PureFox48
Copy link

Incidentally, if you want to recover the letters we started with rather than the corresponding numbers, fmt.write has a '$c" verb which converts from a numeric codepoint to its unicode character and saves you having to write your own routine to do this.

So, if we replace the 'newPuzzle' function in the previous version with the following:

var newPuzzle = Fn.new { |data|
    var rowData = p.splitAll(data[0])
    var colData = p.splitAll(data[1])
    var rows = getCandidates.call(rowData, colData.count)
    var cols = getCandidates.call(colData, rowData.count)

    while (true) {
        var numChanged = reduceMutual.call(cols, rows)
        if (numChanged == -1) {
            System.print("No solution")
            return
        }
        if (numChanged <= 0) break
    }

    var rowCounts = []
    var colCounts = []

    for (r in 0...rows.count) {
        var rowCount = []
        var count = 0
        var row = rows[r]
        for (c in 0...cols.count) {
            if (row[0][c]) {
                count = count + 1
            } else if (count > 0) {
                rowCount.add(count)
                count = 0
            }
        }
        if (count > 0) rowCount.add(count)
        rowCounts.add(rowCount)
    }

    for (c in 0...cols.count) {
        var colCount = []
        var count = 0
        for (r in 0...rows.count) {
            var row = rows[r]
            if (row[0][c]) {
                count = count + 1
            } else if (count > 0) {
                colCount.add(count)
                count = 0
            }
        }
        if (count > 0) colCount.add(count)
        colCounts.add(colCount)
    }

    var maxColCount = 0
    for (cc in colCounts) {
        if (cc.count > maxColCount) maxColCount = cc.count
    }

    for (r in 0...rows.count) {
        var row = rows[r]
        for (c in 0...cols.count) {
            System.write(row[0][c] ? "# " : ". ")
        }
        for (rc in 0...rowCounts[r].count) {
            Fmt.write("$c", rowCounts[r][rc] + 64)
        }
        System.print()
    }

    for (i in 1..maxColCount) {
        for (cc in colCounts) {
            if (i <= cc.count) Fmt.write("$c ", cc[i-1] + 64) else System.write("  ")
        }
        System.print()
    }
    System.print()
}

we now get:

. # # # . . . . C
# # . # . . . . BA
. # # # . . # # CB
. . # # . . # # BB
. . # # # # # # F
# . # # # # # . AE
# # # # # # . . F
. . . . # . . . A
. . . # # . . . B
A C A G E C D C 
B A E A         

. . . . . . . . . . # # # # # # . . . . F
. . . . . . . . # # # . # . . # # # . . CAC
. . . # . . # # # . . . # . . . . # # # ACAC
. . # # # . # # # # # # # # # # # # # # CN
. . . # . . # . . . . . . . . . . . . # AAA
. . # . # . # # . . . . . . . . . . # # AABB
# # # # # . . # # . . . . . . . . # # . EBB
# # # # # . . . # . . . . . . . . # . . EAA
# # # # # . . # # # . # # # . # # # . . ECCC
# # # # # # # # . # # # . # # # . # # # HCCC
D D A C A A D B C A B A D A A B A C B D 
    E D E   A B C A A A A A A A A D B A 
              B   B A B   B A B A   A   

. . . . # # # . # . . . . . . . . . . . CA
. . . . # # . # # # # . # . . . . . . . BDA
. . . . # . # # # . # # # . . . . . . . ACC
. . # # . # # # # . . . . . . . . . . . BD
. # # # . # # # . # . . . . # # # . . . CCAC
# # # . . # # . # # . . . # . # # # . . CBBAC
# # . . # # . # # . . . . # # . # # . . BBBBB
. . . . # # . # . # . . # # . # . # . . BAABAA
. . . . # . # # . # . . . # # # # . . . ABAD
. . . . # . # . # # . . . . . # # . . . AABB
. . . . . # # . # # . . # # # # # # # # BBH
. . . . # # . # # . . . # # . . # # # # BBBD
. . . . # . # # . # # . # . . . # . . # ABBAAA
# # # . . # # # . # # # # # . . . . . # CCEA
# . # . # # # . # . . . . # . . . . # # AACAAB
# # . . # # # . # . . . . # # # . # # # BCACC
. # . # # # . # # . # # # # # # # # . . ACBH
. # # # # . # # # . # # # # # # # # . . DCH
. . . # . # # # # . # # . # # # # # . . ADBE
. . . # . # # # # . # # . . . # # . . . ADBB
. . . . # # # # . . # # . . . # # # # # DBE
. . . # # # # # . # # # . . . # # # # # ECE
. . . # # # # . # . . . . . . . . . . # DAA
. . # # # # . # # . . . . . . . . . . . DB
. . # # # . # # # . . . . . . . . . . . CC
B C C B C B A D D A B A B D A B C C B F 
C A B D D E D C B B B A A B A D E B B C 
  C A D B B C C C D F F D F A G F D B   
    B   D D D F F B     B   A     B     
        E F F B C A         D           
            A                           

. . . . . . . . . . . . . . . . . . . . # # # # # E
. . # # . . . . . . . . . . . . . . # # # . . # # BCB
. # # . . . . . . . . . . . . . . # # # # # . . # BEA
# # . . . . . . . . . . . . . # # # # # # # # . . BH
# # . . . . # # # # # . # # # # # # # # # # # . . BEK
# . # . . # # . . . . # . . . . # # # # # # . . . AABAF
# . . # # . . . . . # . . . . . . . # # # . . . . ABAC
# # . . . . . . . . # . . . . . . . . . . . . . # BAA
. # # . . . . . # # # # # # . . . . . . . . . # # BFB
. . # # # # # # # # # # # # # # # . . . . # # # # OD
. . . . . # # # # # # # # # # . . # # # # # # # # JH
. . . . # # . # . # # # # . # # # . . # # # # # # BADCF
. . . . . . . . # # # # # # # # # # # # # # # # # Q
. . . . . . . . # # # # # # # # # # # # # # # # # Q
. . . . . . . # # # # # # # # # # # # # # # # # # R
. . . . . . . # . . . # # # # # # # # # # # # # # AN
. . . . . . . # . # . # # # # # # # # # # # # # # AAN
. . . . . . . . # # # # # . . . # # # # # # # # # EI
. . . . . . . . . . . . . . . . . # # # # # # # # H
. . . . . . . . . . . . . . . . . . # # # # # # # G
E C B A A A B A A A A A A A A B C D F F G A A B C 
  B A A A C B C C G I J J C H A A A A J J D B L M 
    B A A     C C B A     E   F G G H     K K     
                A                                 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants