I have been working on an algorithm (Dafny cannot prove function-method equivalence, with High-Order-Polymorphic Recursive vs Linear Iterative) to count the number of subsequences of a sequence that hold a property P. For instance, how many subsequences hold that 'the number of positives on its left part are more that on its right part'.
But this was just to offer some context.
The important function is this CountAux function below. Given a proposition P (like, x is positive), a sequ sequence of sequences, an index i to move through the sequences, and an upper bound j:
function CountAux<T>(P: T -> bool, sequ: seq<T>, i: int, j:int): int
requires 0 <= i <= j <= |sequ|
decreases j - i //necessary to prove termination
ensures CountAux(P,sequ,i,j)>=0;
{
if i == j then 0
else (if P(sequ[i]) then 1 else 0) + CountAux(P, sequ, i+1,j)
}
To finish with it, now, it turns out I need a couple of lemmas (which I strongly believe they are true). But I have no idea how to do prove, could anyone help or provide the proofs? Do not seem difficult, but I am not used to prove in Dafny (sure they can be done using structural induction).
These are the lemmas I would like to prove:
lemma countLemma1<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int)
requires 0<=i<=k<=j<=|sequ|
ensures CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j)
//i.e. [i,k) [k,j)
{
if sequ == [] {
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else{
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
}
lemma countLemma2<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int,l:int)
requires 0<=i<=j<=|sequ| && 0<=k<=l<=j-i
ensures CountAux(P,sequ[i..j],k,l)==CountAux(P,sequ,i+k,i+l)
//that is, counting the subsequence is the same as counting the original sequence with certain displacements
{
if sequ == [] {
assert CountAux(P,sequ[i..j],k,l)==CountAux(P,sequ,i+k,i+l);
}
else{
assert CountAux(P,sequ[i..j],k,l)==CountAux(P,sequ,i+k,i+l);
}
}
EDIT:
I have been trying but it seems I am misunderstanding structural induction. I identified three basic cases. Out of them, I see that if i==0, then the induction should hold (it fails), and therefore if i>0 I try to reach the i==0 using induction:
lemma countID<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int)//[i,k) [k,j)
requires 0<=i<=k<=j<=|sequ|
ensures CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j)
{
if sequ == [] || (j==0) || (k==0) {
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else {
if (i==0) {
countID(P,sequ[1..],i,j-1,k-1);
assert CountAux(P,sequ[1..],i,j-1)
==CountAux(P,sequ[1..],i,k-1)+CountAux(P,sequ[1..],k-1,j-1);
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else{
//countID(P,sequ[i..],0,j-i,k-i);
//assert CountAux(P,sequ[i..],0,j-i)
// ==CountAux(P,sequ[i..],0,k-i)+CountAux(P,sequ[i..],k-i,j-i);
countID(P,sequ[1..],i-1,j-1,k-1);
assert CountAux(P,sequ[1..],i-1,j-1)
==CountAux(P,sequ[1..],i-1,k-1)+CountAux(P,sequ[1..],k-1,j-1);
}
//assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
}
You can prove your lemma in recursive manner.
You can refer https://www.rise4fun.com/Dafny/tutorialcontent/Lemmas#h25 for detailed explanation. It also has an example which happens to be very similar to your problem.
lemma countLemma1<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int)
requires 0<=i<=k<=j<=|sequ|
ensures CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j)
decreases j - i
//i.e. [i,k) [k,j)
{
if i == j {
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else{
if i == k {
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
else {
countLemma1(P, sequ, i+1, j, k);
assert CountAux(P,sequ,i,j)==CountAux(P,sequ,i,k)+CountAux(P,sequ,k,j);
}
}
}
lemma countLemma2<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int,l:int)
requires 0<=i<=j<=|sequ| && 0<=k<=l<=j-i
ensures CountAux(P,sequ[i..j],k,l)==CountAux(P,sequ,i+k,i+l)
decreases j - i
//that is, counting the subsequence is the same as counting the original sequence with certain displacements
{
if i == j {
assert CountAux(P,sequ[i..j],k,l) == CountAux(P,sequ,i+k,i+l);
}
else{
if k == l {
assert CountAux(P,sequ[i..j],k,l) == CountAux(P,sequ,i+k,i+l);
}
else {
countLemma1(P, sequ[i..j], k, l, l-1);
assert CountAux(P,sequ[i..j],k,l) == CountAux(P,sequ[i..j],k,l-1) + CountAux(P,sequ[i..j],l-1,l);
countLemma1(P, sequ, i+k, i+l, i+l-1);
assert CountAux(P,sequ,i+k,i+l) == CountAux(P,sequ,i+k,i+l-1) + CountAux(P,sequ,i+l-1,i+l);
countLemma2(P, sequ, i, j-1, k ,l-1);
assert CountAux(P,sequ[i..(j-1)],k,l-1) == CountAux(P,sequ,i+k,i+l-1);
lastIndexDoesntMatter(P, sequ, i,j,k,l);
assert CountAux(P,sequ[i..j],k,l-1) == CountAux(P,sequ[i..(j-1)],k,l-1); // this part is what requires two additional lemmas
assert CountAux(P,sequ[i..j],l-1,l) == CountAux(P,sequ,i+l-1,i+l);
assert CountAux(P,sequ[i..j],k,l) == CountAux(P,sequ,i+k,i+l);
}
}
}
lemma lastIndexDoesntMatter<T>(P: T -> bool, sequ: seq<T>,i:int,j:int,k:int,l:int)
requires i != j
requires k != l
requires 0<=i<=j<=|sequ| && 0<=k<=l<=j-i
ensures CountAux(P,sequ[i..j],k,l-1) == CountAux(P,sequ[i..(j-1)],k,l-1)
{
assert l-1 < j;
if j == i + 1 {
}
else {
unusedLastIndex(P, sequ[i..j], k, l-1);
assert sequ[i..(j-1)] == sequ[i..j][0..(|sequ[i..j]|-1)];
assert CountAux(P,sequ[i..j],k,l-1) == CountAux(P,sequ[i..(j-1)],k,l-1);
}
}
lemma unusedLastIndex<T>(P: T -> bool, sequ: seq<T>, i: int, j:int)
requires 1 < |sequ|
requires 0 <= i <= j < |sequ|
ensures CountAux(P,sequ,i,j) == CountAux(P,sequ[0..(|sequ|-1)],i,j)
decreases j-i
{
if i == j{
}
else {
unusedLastIndex(P, sequ, i+1, j);
}
}
sql
CREATE TABLE public.tiantang_page (
href varchar NOT NULL,
status int4 NOT NULL,
description varchar NOT NULL,
urls url[] NULL
);
CREATE TYPE url AS (
url varchar,
status int4);
insert composite type array
type url struct {
url string
status int
}
var urls [1]url
urls[0] = url{
url: "",
status: 0,
}
update := "UPDATE \"public\".\"tiantang_page\" SET \"urls\"=$1 where \"href\"=$2;"
r, err := db.Exec(update, pq.Array(urls),href)
if err != nil {
log.Fatal(err)
}
error
sql: converting argument $1 type: unsupported type parsetest.url, a struct
library
https://godoc.org/github.com/lib/pq
Note that custom composite types are not fully supported by lib/pq.
If all you want is to be able to store the urls then the simplest approach would be to implement the driver.Valuer interface on the url type and then use it as you do with pq.Array:
func (u url) Value() (driver.Value, error) {
return fmt.Sprintf("(%s,%d)", u.url, u.status), nil
}
// ...
r, err := db.Exec(update, pq.Array(urls), href)
more info on that can be found here: https://github.com/lib/pq/issues/544
Note that I haven't tried this with arrays, only with slices, so you may have to switch from using an array to using a slice, i.e. instead of var urls [1]url you would use var urls = make([]url, 1).
If you also want to be able to retrieve the array of urls back from the db, then you'll have to implement the sql.Scanner interface, however here the pq.Array is not very reliable and you'll have to implement the scanner on the slice type and do all the parsing yourself.
The general format of composite types is (val1, val2, ...) note that you have to put double quotes around values that contain commas or parentheses. For example to construct a value of the url type you would use the literal expression: (http://example.com,4). More info in the docs.
The format for an array of composite types is {"(val1, val2, ...)" [, ...]}, note that in this case if you need to put double quotes around the values you need to escape them. For example {"(http://example.com,4)","(\"http://example.com/?list=foo,bar,baz\",3)"}
So as you can see the more complex the data in the composite type the more complex will be the parsing as well.
Here's a crude example (does not handle quoted values):
type urlslice []url
func (s *urlslice) Scan(src interface{}) error {
var a []byte // the pq array as bytes
switch v := src.(type) {
case []byte:
a = v
case string:
a = []byte(v)
case nil:
*s = nil
return nil
default:
return fmt.Errorf("urlslice.Scan unexpected src type %T", src)
}
a = a[1 : len(a)-1] // drop curly braces
for i := 0; i < len(a); i++ {
if a[i] == '"' && (len(a) > (i+1) && a[i+1] == '(') { // element start?
i += 2 // move past `"(`
j := i // start of url.url
u := url{}
for ; i < len(a) && a[i] != ','; i++ {
}
u.url = string(a[j:i])
i += 1 // move past `,`
j = i // start of url.status
for ; i < len(a) && a[i] != ')'; i++ {
}
i64, err := strconv.ParseInt(string(a[j:i]), 10, 64)
if err != nil {
return err
}
u.status = int(i64)
*s = append(*s, u)
i += 2 // move past `)",`
}
}
return nil
}
for completeness, here's the Valuer interface implemented by the slice type, again not handling proper quoting of values that may require it:
func (s urlslice) Value() (driver.Value, error) {
data := []byte{'{'}
for _, url := range s {
data = append(data, '"', '(')
data = append(data, []byte(url.url)...)
data = append(data, ',')
data = strconv.AppendInt(data, int64(url.status), 10)
data = append(data, ')', '"', ',')
}
data[len(data)-1] = '}' // replace last ',' with '}' to close the array
return data, nil
}
With the urlslice implementing the two interfaces directly you can stop using pq.Array.
var urls = urlslice{{
url: "http://example.com",
status: 4,
}}
update := `UPDATE "public"."tiantang_page" SET "urls"=$1 where "href"=$2`
r, err := db.Exec(update, urls, href)
if err != nil {
log.Fatal(err)
}
var urls2 urlslice
selurls := `SELECT "urls" FROM "public"."tiantang_page" where "href" = $1`
if err := db.QueryRow(selurls, href).Scan(&urls2); err != nil {
log.Fatal(err)
}
Please keep in mind that both of the above examples should be considered only as hints of the direction to take in solving this problem. Not only are the two examples incomplete in that they don't handle quoted values, but they are also not very elegant implementations.
Reasonably complete composite literal parser:
type parseState int
const (
state_initial parseState = iota // start
state_value_start // no bytes read from value yet
state_value // unquoted value
state_quoted // inside quote
state_value_end // after a close quote
state_end // after close paren
)
func parseComposite(in []byte) ([]string, error) {
state := state_initial
ret := []string{}
val := []byte{}
for _, b := range in {
switch state {
case state_initial:
if b != '(' {
return nil, fmt.Errorf("initial character not ')': %v", in)
} else {
state = state_value_start
}
case state_value_start:
if b == '"' {
state = state_quoted
continue
}
fallthrough
case state_value:
if b == ',' {
ret = append(ret, string(val))
val = nil
state = state_value_start
} else if b == ')' {
ret = append(ret, string(val))
val = nil
state = state_end
} else {
val = append(val, b)
}
case state_quoted:
if b == '"' {
ret = append(ret, string(val))
val = nil
state = state_value_end
} else {
val = append(val, b)
}
case state_value_end:
if b == ',' {
state = state_value_start
} else if b == ')' {
state = state_end
} else {
return nil, fmt.Errorf("invalid delimiter after closing quote: %v", in)
}
case state_end:
return nil, fmt.Errorf("trailing bytes: %v", in)
}
}
if state != state_end {
return nil, fmt.Errorf("unterminated value: %v", in)
}
return ret, nil
}
I'm parsing a form in Go and I frequently find groups of checkboxes which need to be processed into text like so:
[ ] Foo
[x] Bar
[ ] Baz
[x] Bat
where the output should be a comma-separated list "BarText, BatText" corresponding to the checked items, or "None" if none of the items are checked. What is a good way to handle this situation? Repeating the logic each time seems like a bad idea.
In the spirit of YAGNI there's no need to handle possible future changes like translations into other languages (actually this example is highly unlikely to be useful in the present context).
Efficiency is unimportant for this application.
Edit: code looks like this (source):
func handleCheckboxesForm(w http.ResponseWriter, r *http.Request) {
b := func(name string) string { // helper function for boolean values in the form
return r.FormValue(name) == "on"
}
text := "Header stuff here"
mytext := ""
if b("nfpa-alk") {
mytext += ", alkaline"
}
if b("nfpa-acid") {
mytext += ", acid"
}
if b("nfpa-w") {
mytext += ", reacts violently with water"
}
if b("nfpa-alk") || b("nfpa-acid") || b("nfpa-w") {
text += mytext[2:] + "\n"
} else {
text += "none\n"
}
// lots of other checkbox groups here
// do stuff with text
}
There are many repeating code in yours which can be optimized out.
Your code must contain at least the following "fragments":
The mappings from entry name to entry text, which can be stored in a map, e.g.
var mappings = map[string]string {
"Foo": "Foo text",
"Bar": "Bar text",
"Baz": "Baz text",
"Bat": "Bat text",
// ... other mappings
}
And the list of keys belonging to a group, which can be stored in a slice, e.g.
var group1 = []string{"Foo", "Bar", "Baz", "Bat"}
Once you defined these, you can have a helper method which handles a group:
func handleGroup(r *http.Request, group []string) (res string) {
for _, v := range group {
if r.FormValue(v) == "on" {
res := ", " + mappings[v]
}
}
if res == "" {
return "none\n"
}
return res[2:] + "\n"
}
That's all. After this your handler can be this simple:
func checkboxHandler(w http.ResponseWriter, r *http.Request) {
// Handle group1:
res1 := handleGroup(r, group1)
// Handle group2:
res2 := handleGroup(r, group2)
}
Notes:
It wasn't your requirement, but this solution handles translations very easily: each translation can have its own mappings map, and that's all. Nothing else needs to be changed.
Performance also wasn't your concern, but appending strings isn't very efficient this way. If performance is at least a little concern, you can improve it without adding complexity by utilizing bytes.Buffer:
func handleGroup(r *http.Request, group []string) string {
buf := &bytes.Buffer{}
for _, v := range group {
if r.FormValue(v) == "on" {
buf.WriteString(", ")
buf.WriteString(mappings[v])
}
}
if buf.Len() == 0 {
return "none\n"
}
buf.WriteString("\n")
return string(buf.Bytes()[2:])
}
This will store the form values into an array.
Then, it will iterate the array into a string with appending "," at the end of each name.
Then, it will put very last ", " (2 bytes) if it's longer than 2, otherwise, print "None"
func(w http.ResponseWriter, r *http.Request) {
r.ParseMultipartForm(0)
arr := []string{}
if r.FormValue("Foo") {
arr = append(arr, "Foo")
}
if r.FormValue("Bar") {
arr = append(arr, "Bar")
}
if r.FormValue("Baz") {
arr = append(arr, "Baz")
}
if r.FormValue("Bat") {
arr = append(arr, "Bat")
}
out := ""
for _, title := range arr {
out += title +", "
}
if len(out) > 2 {
out := out[0: len(out)-2]
} else {
out = "None"
}
fmt.Println(out)
}
If you want to iterate,
for k, vs:= range r.Form {
for _, v:= range vs{
fmt.Println(k, v)
}
}
I have a for loop that checks if a number is a factor of a number, then checks if that factor is prime, and then it adds it to an array. Depending on the original number, I will get an error saying
fatal error: Can't form range with end < start
This happens almost every time, but for some numbers it works fine. The only numbers I have found to work with it are 9, 15, and 25.
Here is the code:
let num = 16 // or any Int
var primes = [Int]()
for i in 2...(num/2) {
if ((num % i) == 0) {
var isPrimeFactor = true
for l in 2...i-1 {
if ((i%l) == 0) {
isPrimeFactor = false;
}//end if
}//end for
if (isPrimeFactor == true) {
primes.append(i)
}//end if
}//end if
}//end for
Swift 5
If you need a loop with dynamic value-range, I suggest that using stride(to:by:) instead of ..< or ...
Basically ..< or ... will be crashed if start_index > end_index.
This will be crash:
let k = 5
for i in 10...k { print("i=\(i)") }
for i in 10..<k { print("i=\(i)") }
How to fix:
let k = 5
for i in stride(from: 10, through: k, by: 1) { print("i=\(i)") }
for i in stride(from: 10, to: k, by: 1) { print("i=\(i)") }
NOTE:
The code above won't print out anything, but it won't be crash when execution.
Also, if you want to stride from a higher number to a lower number then the by parameter needs to be changed to a negative number.
Reference:
http://michael-brown.net/2016/using-stride-to-convert-c-style-for-loops-to-swift-2.2/
http://swiftdoc.org/v2.1/protocol/Strideable/
In your second loop, i will always start at 2, which means you're looping from 2...1
SWIIFT 4
The best way to go is to use stride as by this documentation page:
Generic Function stride(from:to:by:)
for i in stride(from: 10, through: 5, by: -1) { print(i) }
and stride through if you want to include the lowerBound: Generic Function stride(from:through:by:)
Both ClosedRange and CountableRange throw this error unless start <= end. One problem with using stride(from:to:by) is that it returns a Strideable and not a Range, which doesn't work with the "is in range" operator ~=. To handle these cases, I use an extension which gives me a bounds-safe range, where invalid ranges become an empty range:
extension Int {
func until(_ end: Int) -> CountableRange<Int> {
return self <= end ? self..<end : self..<self
}
func through(_ end: Int) -> CountableRange<Int> {
return self <= end ? self..<(end + 1) : self..<self
}
}
Both return CountableRange so that an invalid through range becomes an empty range. (Side note: the name until is chosen because this "safe" range behaves the same as until ranges in Kotlin/Android).
Usage:
for i in 0.until(3) { /* do something */ }
let printRange = { (range: Range<Int>) -> Void in
for i in range {
print(i, terminator: " ")
}
print()
}
printRange(0.until(3)) // prints "0 1 2"
printRange(0.until(0)) // prints ""
printRange(3.until(0)) // prints ""
printRange(0.through(3)) // prints "0 1 2 3"
printRange(0.through(0)) // prints "0"
printRange(3.through(0)) // prints ""
print(0.until(1) ~= -1) // prints "false"
print(0.until(1) ~= 0) // prints "true"
print(0.until(1) ~= 1) // prints "false"
print(0.until(0) ~= 0) // prints "false"
print(1.until(0) ~= 0) // prints "false"
print(0.through(1) ~= -1) // prints "false"
print(0.through(1) ~= 0) // prints "true"
print(0.through(1) ~= 1) // prints "true"
print(0.through(0) ~= 0) // prints "true"
print(1.through(0) ~= 0) // prints "false"
If you want to use range where upperBound < lowerBound, you can add reversed() to it.
for eg: for number in (0...highestPossibleNumber).reversed()
Using a simple solution you can make for loop reverse using Stride and -
func reverseArray(oldarray: [String]) -> [String] {
var newArray = [String]()
let len = oldarray.count
for i in stride(from: len - 1, through: 0, by: -1)
{ newArray.append(oldarray[i])
print(i)
}
return newArray
}
input : print(reverseArray(oldarray: ["World", "Hello"]))
output : ["Hello", "World"]
The easiest solution is to apply ".reversed()" to your array.
Example: array.reversed()