Comparing multiplication-tables in F# - f#

I'm trying to compare two ways of printing a multiplication table, and even though they print identical strings when i printf "%s" mulTable n and printf "%s" loopMulTable n, they dont seem to be the same thing when comparing them, as it prints false for every comparison in the last function. Can anyone explain to me why?
let a = " 1 2 3 4 5 6 7 8 9 10
1 1 2 3 4 5 6 7 8 9 10
2 2 4 6 8 10 12 14 16 18 20
3 3 6 9 12 15 18 21 24 27 30
4 4 8 12 16 20 24 28 32 36 40
5 5 10 15 20 25 30 35 40 45 50
6 6 12 18 24 30 36 42 48 54 60
7 7 14 21 28 35 42 49 56 63 70
8 8 16 24 32 40 48 56 64 72 80
9 9 18 27 36 45 54 63 72 81 90
10 10 20 30 40 50 60 70 80 90 100"
let mulTable n =
a.[0..(n*54)+51]
let loopMulTable n =
let mutable returnString = ""
returnString <- returnString + (sprintf " ")
for i in 1..10 do
returnString <- returnString + (sprintf "%5d" i)
for x in 1..n do
returnString <- returnString + (sprintf "\n")
returnString <- returnString + (sprintf "%2d" x)
for y in 1..10 do
returnString <- returnString + (sprintf "%5d" (x*y))
returnString
let o = "n:"
let u = "boolean value:"
let chooseN n =
printfn "%5s %19s" o u
for n in 1..n do
printfn "%4d %15b" n ((loopMulTable n)=(mulTable n))
chooseN 5
Might i add that i am a beginner in programming and especially in F#, so there might be other flaws though they're not the problem that i'm looking to solve.
Thanks!

The test for equality is most likely failing because this line is appending a newline rather than a carriage-return-newline combination.
returnString <- returnString + (sprintf "\n")
If you are on a Windows machine, the line breaks in your source code will most likely include the carriage return character. Change it to the following and it should compare just fine:
returnString <- returnString + (sprintf "\r\n")

Related

Maxima collecting specific terms in an expression

I have an expression that actually can be expressed in simple form by collecting the specific terms. I have problem in Maxima to substitute or simplify the expression to the known terms.
(%i1) expr:(16*h^2*v_0^2+(38*h*u_0-38*h*u_1)*v_0+25*u_1^2-50*u_0*u_1+25*u_0^2)/3;
2 2 2 2
16 h v_0 + (38 h u_0 - 38 h u_1) v_0 + 25 u_1 - 50 u_0 u_1 + 25 u_0
(%o1) -----------------------------------------------------------------------
3
(%i2) eq1:a1=-h*v_0+2*u_1-2*u_0;
eq2:a2=-2*(h*v_0-u_1+u_0);
(%o2) a1 = (- h v_0) + 2 u_1 - 2 u_0
(%i3)
(%o3) a2 = - 2 (h v_0 - u_1 + u_0)
(%i4) subst([eq1,eq2],expr);
2 2 2 2
16 h v_0 + (38 h u_0 - 38 h u_1) v_0 + 25 u_1 - 50 u_0 u_1 + 25 u_0
(%o4) -----------------------------------------------------------------------
3
What I want is something like this
expr=c1*(a1)^q1 + c2*(a2)^q2
where c1,c2,q1,q2 are the constant that would generated by simplifying expr using known term a1,a2. How to do that? Is there any specific syntax?

Deedle - what is most efficient (fastest) way to replace an item in a column based on value of another item in another column on the same row

I have this data frame
AutoStat_1 AutoStat_2 Mode_1 Mode_2 Setpoint_1 Setpoint_2
0 -> 0 0 1 1 23 24
1 -> 0 1 1 0 23 27
2 -> 1 1 3 0 26 27
3 -> 1 0 3 1 26 24
4 -> 0 0 1 2 24 24
5 -> 0 0 1 2 24 24
6 -> 2 3 0 4 24 26
7 -> 2 3 0 4 25 26
The requirement is that if AutoStat_i is not 0 then Mode_i and Setpoint_i will be the value of the above (in-front) of which AutoStat_i is 0
The result should be (notice the column Setpoint_i and Mode_i are different than above)
AutoStat_1 AutoStat_2 Mode_1 Mode_2 Setpoint_1 Setpoint_2
0 -> 0 0 1 1 23 24
1 -> 0 1 1 1 23 24
2 -> 1 1 1 1 23 24
3 -> 1 0 1 1 23 24
4 -> 0 0 1 2 24 24
5 -> 0 0 1 2 24 24
6 -> 2 3 1 2 24 24
7 -> 2 3 1 2 24 24
What've I tried:
My idea is for each set i of (AutoStat_i, Mode_i, Setpoint_i), scan each row if AutoStat_i is <> 0 then set the other values to NaN, after that I will just do the fillMissing with Direction.Forward. Below is the impementation
let calculateNonSFi (df:Frame<_,string>) idx =
let autoStatusName = sprintf "AutoStat_%d" idx
let setpointName = sprintf "Setpoint_%d" idx
let modeName = sprintf "Mode_%d" idx
let setMissingOnMode (s:ObjectSeries<string>) =
let s2 = s.As<float>()
if s2.[autoStatusName] <> 0. then
Series.replaceArray [|setpointName;modeName|] Double.NaN s2
else
s2
df.Rows
|> Series.mapValues setMissingOnMode
|> Frame.ofRows
|> Frame.fillMissing Direction.Forward
|> Frame.fillMissing Direction.Backward
// for each set i do the folding
[0..150]
|> List.fold calculateNonSFi df
It gave me the expected results, however, for 150sets of 8000rows, it took more than 30 minutes to complete. I kinda see where it's wrong as for every set it acts on the whole dataset but I cannot think of a better way.
The logic is quite simple. I believe there should be a better way, do advice, thanks.
UPDATE
Here is the code for reproduction
open Deedle
open System
let df =
[
{| AutoStat_1=0;Setpoint_1=23;Mode_1=1;AutoStat_2=0;Setpoint_2=24;Mode_2=1|}
{| AutoStat_1=0;Setpoint_1=23;Mode_1=1;AutoStat_2=1;Setpoint_2=24;Mode_2=1|}
{| AutoStat_1=1;Setpoint_1=23;Mode_1=1;AutoStat_2=1;Setpoint_2=24;Mode_2=1|}
{| AutoStat_1=1;Setpoint_1=23;Mode_1=1;AutoStat_2=0;Setpoint_2=24;Mode_2=1|}
{| AutoStat_1=0;Setpoint_1=24;Mode_1=1;AutoStat_2=0;Setpoint_2=24;Mode_2=2|}
{| AutoStat_1=0;Setpoint_1=24;Mode_1=1;AutoStat_2=0;Setpoint_2=24;Mode_2=2|}
{| AutoStat_1=2;Setpoint_1=24;Mode_1=1;AutoStat_2=3;Setpoint_2=24;Mode_2=2|}
{| AutoStat_1=2;Setpoint_1=24;Mode_1=1;AutoStat_2=3;Setpoint_2=24;Mode_2=2|}
] |> Frame.ofRecords
df.Print()
let calculateNonSFi (df:Frame<_,string>) idx =
let autoStatusName = sprintf "AutoStat_%d" idx
let setpointName = sprintf "Setpoint_%d" idx
let modeName = sprintf "Mode_%d" idx
let setMissingOnMode (s:ObjectSeries<string>) =
let s2 = s.As<float>()
if s2.[autoStatusName] <> 0. then
Series.replaceArray [|setpointName;modeName|] Double.NaN s2
else
s2
df.Rows
|> Series.mapValues setMissingOnMode
|> Frame.ofRows
|> Frame.fillMissing Direction.Forward
let df1 =
[1..2]
|> List.fold calculateNonSFi df
df1.Print()
Advice/Answer from Tomas
df
|> Frame.mapRows (fun _ o ->
[ for i in 0 .. 150 do
let au = o.GetAs<float>("AutoStat_" + string i)
yield "AutoStat_" + string i, au
yield "Mode_" + string i, if au <> 0. then nan else o.GetAs("Mode_" + string i)
yield "Setpoint_" + string i, if au <> 0. then nan else o.GetAs("Setpoint_" + string i) ]
|> series )
|> Frame.ofRows
|> Frame.fillMissing Direction.Forward
which yields correct result but in different column order hence my mistake in the earlier edit
AutoStat_1 Mode_1 Setpoint_1 AutoStat_2 Mode_2 Setpoint_2
0 -> 0 1 23 0 1 24
1 -> 0 1 23 1 1 24
2 -> 1 1 23 1 1 24
3 -> 1 1 23 0 1 24
4 -> 0 1 24 0 2 24
5 -> 0 1 24 0 2 24
6 -> 2 1 24 3 2 24
7 -> 2 1 24 3 2 24
First of all, I think your strategy of setting Mode_i and Setpoint_i to NA when AutoStat_i is not 0 and then filling the missing values is a nice approach.
You can certainly make it a bit faster by moving the fillMissing call outside of the calculateNonSFi function - the fillMissing operation will run on the whole frame, so you need to run this once at the end.
The second thing would be to find a way of setting the NA values that only iterates over the frame once. One option (I have not tested this) would be to use Frame.mapRows and, inside the function, iterate over all the columns (rather than iterating over all the columns and calling mapRows repeatedly). Something like:
df
|> Frame.mapRows (fun _ o ->
[ for i in 0 .. 150 do
let au = o.GetAs<float>("AutoStat_" + string i)
yield "AutoStat_" + string i, au
yield "Mode_" + string i, if au = 0. then nan else o.GetAs("Mode_" + string i)
yield "Setpoint_" + string i, if au = 0. then nan else o.GetAs("Setpoint_" + string i) ]
|> series )
|> Frame.ofRows

Why is Swift 5 String(Int) Failing when a Big Integer of over 20 digits?

I wrote the above-referenced simple code to check if integers in the Fibonacci sequence do not contain 0 or 5, and reduce to 1237, if the integer only contains 1,2,3,4,6,7,8, or 9 as digits; and if so, to then print the member of the sequence. Interestingly from a numbers game perspective, there are only 23 such integers in the Fibonacci sequence.
I have to use the Swift-BigInt library for when the integers get large:
func getFib1237s() {
// Some temporary variables.
var a = BInt(0)
var b = BInt(1)
var m = BInt(1)
var i = BInt(0)
var z = BInt(1)
// Get the numbers until crash...
while i < z {
let temp = a
a = b
b = b + temp
print("a: ", a)
var str = String(a)
print("String start: ", str)
str = str.replacingOccurrences(of: "9", with: "3")
print("String after 9 reducto: ", str)
str = str.replacingOccurrences(of: "6", with: "23")
print("String after 6 reducto: ", str)
str = str.replacingOccurrences(of: "8", with: "2")
print("String after 8 reducto: ", str)
str = str.replacingOccurrences(of: "4", with: "2")
print("String after 4 reducto: ", str)
if (str.firstIndex(of:"5") == nil) && (str.firstIndex(of: "0") == nil) && str.contains("1") && str.contains("2") && str.contains("3") && str.contains("7") {
print(m, "Fib 1237 number is ", a, " | Digits: ", str.count)
m+=1
}
i+=1
z+=1
}
}
Apparently, at or around the 20-digit mark, the String() method fails and throws errors, not performing the check, because, according to the debugger, the integer is being changed to random other integer entirely.
So, are there any BigInt or String workaround/alternatives in Swift? I wrote Ruby code that works fine in Xcode, but am trying to exclusively use Swift (and metal) for this project which ultimately needs to work on iOS for commercial/production purposes.
String(a) calls the String.init overload that takes BinaryInteger. It is very possible that this initialiser is not designed to handle numbers that are super large. You can use a.asString(radix: 10) to convert to string instead.
To make your code work correctly, you should also:
remove the (str.firstIndex(of: "0") == nil)
declare a new string variable and assign the replaced strings to it, otherwise str.count would be incorrect.
I would recommend writing a separate method called reduce, because "reducing" a string requires quite a few steps.
Here is reduce:
func reduce(_ s: String) -> String {
let unique = String(Set(s))
let replaced = unique.replacingOccurrences(of: "9", with: "3")
.replacingOccurrences(of: "6", with: "23")
.replacingOccurrences(of: "8", with: "2")
.replacingOccurrences(of: "4", with: "2")
.replacingOccurrences(of: "0", with: "")
let sortedUniqueAgain = String(Set(replaced).sorted())
return sortedUniqueAgain
}
Now, we can just check whether the return value of this method is 1237:
while m <= 23 {
let temp = a
a = b
b = b + temp
let str = a.asString(radix: 10)
// note that I have declared a new let constant here, instead of assigning to str
// because otherwise str.count will be wrong
let reduced = reduce(str)
if reduced == "1237" {
print(m, "Fib 1237 number is ", a, " | Digits: ", str.count)
m+=1
}
}
Output:
1 Fib 1237 number is 317811 | Digits: 6
2 Fib 1237 number is 2178309 | Digits: 7
3 Fib 1237 number is 267914296 | Digits: 9
4 Fib 1237 number is 701408733 | Digits: 9
5 Fib 1237 number is 1134903170 | Digits: 10
6 Fib 1237 number is 72723460248141 | Digits: 14
7 Fib 1237 number is 117669030460994 | Digits: 15
8 Fib 1237 number is 8944394323791464 | Digits: 16
9 Fib 1237 number is 14472334024676221 | Digits: 17
10 Fib 1237 number is 37889062373143906 | Digits: 17
11 Fib 1237 number is 420196140727489673 | Digits: 18
12 Fib 1237 number is 1100087778366101931 | Digits: 19
13 Fib 1237 number is 1779979416004714189 | Digits: 19
14 Fib 1237 number is 2880067194370816120 | Digits: 19
15 Fib 1237 number is 19740274219868223167 | Digits: 20
16 Fib 1237 number is 83621143489848422977 | Digits: 20
17 Fib 1237 number is 927372692193078999176 | Digits: 21
18 Fib 1237 number is 781774079430987230203437 | Digits: 24
19 Fib 1237 number is 1264937032042997393488322 | Digits: 25
20 Fib 1237 number is 19134702400093278081449423917 | Digits: 29
21 Fib 1237 number is 1983924214061919432247806074196061 | Digits: 34
22 Fib 1237 number is 8404037832974134882743767626780173 | Digits: 34
23 Fib 1237 number is 162926777992448823780908130212788963731840407743629812913410 | Digits: 60

blkparse how to show IO Scheduler message

blktrace version v2.0.0
note: in blkparse output, the m in the sixth column indicate the line is scheduler information.
On Ubuntu 16.04 ext4 I can see the IO Scheduler message, blktrace -d /dev/sda -o - | blkparse -i -
8,0 3 1 0.000000000 24714 A WS 76519424 + 2048 <- (8,1) 76517376
8,0 3 2 0.000000861 24714 Q WS 76519424 + 2048 [TaskSchedulerFo]
8,0 3 3 0.000005084 24714 X WS 76519424 / 76520768 [TaskSchedulerFo]
8,0 3 4 0.000008962 24714 G WS 76519424 + 1344 [TaskSchedulerFo]
8,0 3 5 0.000009379 24714 P N [TaskSchedulerFo]
8,0 3 6 0.000012021 24714 G WS 76520768 + 704 [TaskSchedulerFo]
8,0 3 7 0.000012622 24714 I WS 76519424 + 1344 [TaskSchedulerFo]
8,0 3 0 0.000015209 0 m N cfq24714SN /user.slice insert_request
8,0 3 0 0.000016074 0 m N cfq24714SN /user.slice add_to_rr
8,0 3 0 0.000017548 0 m N cfq24714SN /user.slice preempt
8,0 3 0 0.000018184 0 m N cfq25055SN /user.slice slice expired t=1
8,0 3 0 0.000018982 0 m N cfq25055SN /user.slice resid=-2643710186
8,0 3 0 0.000020125 0 m N /user.slice served: vt=247310740068 min_vt=247310580285
8,0 3 0 0.000021297 0 m N cfq25055SN /user.slice sl_used=33325195 disp=13 charge=13 iops=1 sect=1088
8,0 3 0 0.000021822 0 m N cfq25055SN /user.slice del_from_rr
8,0 3 0 0.000023767 0 m N cfq workload slice:100000000
8,0 3 0 0.000024496 0 m N cfq24714SN /user.slice set_active wl_class:0 wl_type:1
8,0 3 0 0.000025395 0 m N cfq24714SN /user.slice dispatch_insert
8,0 3 0 0.000026232 0 m N cfq24714SN /user.slice dispatched a request
8,0 3 0 0.000026818 0 m N cfq24714SN /user.slice activate rq, drv=1
8,0 3 8 0.000027030 24714 D WS 76519424 + 1344 [TaskSchedulerFo]
8,0 3 9 0.000037848 24714 U N [TaskSchedulerFo] 1
8,0 3 10 0.000038118 24714 P N [TaskSchedulerFo]
8,0 3 11 0.000048153 24714 A WS 76521472 + 264 <- (8,1) 76519424
8,0 3 12 0.000048340 24714 Q WS 76521472 + 264 [TaskSchedulerFo]
8,0 3 13 0.000049444 24714 M WS 76521472 + 264 [TaskSchedulerFo]
8,0 3 14 0.000050486 24714 I WS 76520768 + 968 [TaskSchedulerFo]
8,0 3 0 0.000051332 0 m N cfq24714SN /user.slice insert_request
8,0 3 15 0.000051755 24714 U N [TaskSchedulerFo] 1
8,0 3 0 0.000052418 0 m N cfq24714SN /user.slice dispatch_insert
8,0 3 0 0.000053068 0 m N cfq24714SN /user.slice dispatched a request
8,0 3 0 0.000053604 0 m N cfq24714SN /user.slice activate rq, drv=2
8,0 3 16 0.000053721 24714 D WS 76520768 + 968 [TaskSchedulerFo]
8,0 2 1 0.001844211 0 C WS 76519424 + 1344 [0]
8,0 2 0 0.001849143 0 m N cfq24714SN /user.slice complete rqnoi
on CentOS 7.4 xfs,I can not see the IO Scheduler message, blktrace -d /dev/sdb -o - | blkparse -i -
8,16 25 1 0.000000000 11966 Q R 73400472 + 128 [fio]
8,16 25 2 0.000006237 11966 G R 73400472 + 128 [fio]
8,16 25 3 0.000007806 11966 P N [fio]
8,16 25 4 0.000010836 11966 I R 73400472 + 128 [fio]
8,16 25 5 0.000011878 11966 U N [fio] 1
8,16 25 6 0.000013900 11966 D R 73400472 + 128 [fio]
8,16 10 1 0.008284979 0 C R 73400472 + 128 [0]
8,16 10 2 0.008343574 11966 Q R 73400600 + 128 [fio]
8,16 10 3 0.008345976 11966 G R 73400600 + 128 [fio]
8,16 10 4 0.008346908 11966 P N [fio]
8,16 10 5 0.008348926 11966 I R 73400600 + 128 [fio]
8,16 10 6 0.008349651 11966 U N [fio] 1
8,16 10 7 0.008350694 11966 D R 73400600 + 128 [fio]
8,16 8 1 0.008771249 0 C R 73400600 + 128 [0]
While there are program version differences between the setups (in CentOS 7 blktrace is version 1.0.5 and the kernel is based off 3.10 whereas in Ubuntu 16.04 blktrace is version 1.1.0 and the kernel may be between 4.4 - 4.10) the real point may be down to what was asked (but unfortunately went unanswered) in one of the comments:
what [I/O] scheduler was in use
If we look at one of your m lines:
8,0 3 0 0.000015209 0 m N cfq24714SN /user.slice insert_request
we can see that it is a textual message (hence the m) and that it likely came from the CFQ I/O scheduler (hence the cfq prefix on the message itself). If the I/O scheduler being used for the /dev/sdb device on the CentOS 7 setup was not CFQ (e.g. because the noop I/O scheduler was being used) then we cannot expect similar messages to be present.
So bringing this back to the title of the question:
blkparse how to show IO Scheduler message
If an I/O scheduler wants to it can send free form blktrace text (e.g. see block/cfq-iosched.c which has calls to blk_add_trace_msg() in it) but not all I/O schedulers do (e.g. see block/noop-iosched.c which doesn't even include the linux/blktrace_api.h header). By default blkparse will show all messages present unless you use the -M option to suppress them.

Different YouTube URLs points to the same video

I found some bug in youtube when I reverse engineering it's video id generator. If I change last characther of the video id, it redirects to same video. How is this possible?
Example:
https://www.youtube.com/watch?v=9bZkp7q19f0
https://www.youtube.com/watch?v=9bZkp7q19f1
https://www.youtube.com/watch?v=9bZkp7q19f2
https://www.youtube.com/watch?v=9bZkp7q19f3
But this url isn't work:
https://www.youtube.com/watch?v=9bZkp7q19f4
The videoId is 8 Bytes (64 bit) base64 encoded. From this post :
For the videoId, it is an 8-byte (64-bit) integer. Applying
Base64-encoding to 8 bytes of data requires 11 characters. However,
since each Base64 character conveys exactly 6 bits, this allocation
could actually hold up to 11 × 6 = 66 bits--a surplus of 2 bits over
what our payload needs. The excess bits are set to zero, which has the
effect of excluding certain characters from ever appearing in the last
position of the encoded string. In particular, the videoId will always
end with one of the following: { A, E, I, M, Q, U, Y, c, g, k, o, s,
w, 0, 4, 8 }
In your case, your videoId is 9bZkp7q19f0 :
enc. | 9 b Z k p 7 q 1 9 f | 0
value | 61 27 25 36 41 59 42 53 61 31 | 52
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1101 00
If you modify the last character, the 64 bit id will change if the 4 most significative bit (MSB) are modified :
9bZkp7q19f1 :
enc. | 9 b Z k p 7 q 1 9 f | 1
value | 61 27 25 36 41 59 42 53 61 31 | 53
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1101 01
9bZkp7q19f2 :
enc. | 9 b Z k p 7 q 1 9 f | 2
value | 61 27 25 36 41 59 42 53 61 31 | 54
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1101 10
9bZkp7q19f3 :
enc. | 9 b Z k p 7 q 1 9 f | 3
value | 61 27 25 36 41 59 42 53 61 31 | 55
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1101 11
This will give a different video id (note the 4 MSB of the last Byte are modified 1101 to 1110) :
enc. | 9 b Z k p 7 q 1 9 f | 4
value | 61 27 25 36 41 59 42 53 61 31 | 56
bin. | 111101 011011 011001 100100 101001 111011 101010 110101 111101 011111 | 1110 00
9bZkp7q19f4 will give a different 64 bit id. Note that if such an id exists 9bZkp7q19f4, 9bZkp7q19f5, 9bZkp7q19f6 and 9bZkp7q19f7 will give the same id.
You can check the base64 encoding/values here

Resources