2024-05-10 18:05:03 +00:00
package main
import (
"bufio"
"fmt"
2024-05-10 18:25:23 +00:00
"math"
2024-05-10 18:05:03 +00:00
"os"
"strconv"
"strings"
)
2024-05-10 18:25:23 +00:00
const NORMAL90CONFIDENCE = 1.6448536269514727
func boundsToLogParams ( low float64 , high float64 ) ( float64 , float64 ) {
loglow := math . Log ( low )
loghigh := math . Log ( high )
logmean := ( loghigh + loglow ) / 2.0
logstd := ( loghigh - loglow ) / ( 2.0 * NORMAL90CONFIDENCE )
return logmean , logstd
}
func multiplyLognormals ( logmean1 float64 , logstd1 float64 , logmean2 float64 , logstd2 float64 ) ( float64 , float64 ) {
return logmean1 + logmean2 , math . Sqrt ( logstd1 * logstd1 + logstd2 * logstd2 )
}
func logParamsToBounds ( logmean float64 , logstd float64 ) ( float64 , float64 ) {
h := logstd * NORMAL90CONFIDENCE
loglow := logmean - h
loghigh := logmean + h
return math . Exp ( loglow ) , math . Exp ( loghigh )
}
func combineBounds ( old_low , old_high , new_low , new_high float64 ) ( float64 , float64 ) {
logmean_old , logstd_old := boundsToLogParams ( old_low , old_high )
logmean_new , logstd_new := boundsToLogParams ( new_low , new_high )
logmean_product , logstd_product := multiplyLognormals ( logmean_old , logstd_old , logmean_new , logstd_new )
return logParamsToBounds ( logmean_product , logstd_product )
2024-05-10 18:07:58 +00:00
}
2024-05-10 18:05:03 +00:00
func main ( ) {
2024-05-10 19:14:41 +00:00
var old_low , old_high float64
2024-05-10 18:05:03 +00:00
2024-05-10 21:38:20 +00:00
reader := bufio . NewReader ( os . Stdin )
2024-05-10 18:05:03 +00:00
input , _ := reader . ReadString ( '\n' )
input = strings . TrimSpace ( input )
2024-05-10 18:07:36 +00:00
tokens := strings . Split ( input , " " )
2024-05-10 21:38:20 +00:00
error_msg_start := "Please enter two floats separated by a space, like: 1 10"
2024-05-10 18:07:36 +00:00
if len ( tokens ) != 2 {
2024-05-10 21:38:20 +00:00
fmt . Println ( error_msg_start )
2024-05-10 18:07:36 +00:00
return
}
2024-05-10 18:25:23 +00:00
old_low , err1 := strconv . ParseFloat ( tokens [ 0 ] , 64 )
old_high , err2 := strconv . ParseFloat ( tokens [ 1 ] , 64 )
2024-05-10 18:07:36 +00:00
if err1 != nil || err2 != nil {
2024-05-10 21:38:20 +00:00
fmt . Println ( error_msg_start )
2024-05-10 18:07:36 +00:00
return
}
2024-05-10 18:25:23 +00:00
fmt . Printf ( "=> %.1f %.1f\n" , old_low , old_high )
2024-05-10 18:05:03 +00:00
2024-05-10 21:38:20 +00:00
error_msg_cont := "Please enter two floats separated by a space, like: 1 10, or two floats preceded by a division, like: / 2 20. Or enter i to get the logmean and logstd"
EventForLoop :
2024-05-10 18:05:03 +00:00
for {
2024-05-11 09:27:05 +00:00
var new_low , new_high float64
var err1 , err2 error
2024-05-10 18:05:03 +00:00
input , _ = reader . ReadString ( '\n' )
2024-05-10 18:07:58 +00:00
if strings . TrimSpace ( input ) == "" {
2024-05-10 21:38:20 +00:00
continue EventForLoop
2024-05-10 18:05:03 +00:00
}
2024-05-10 18:07:58 +00:00
tokens := strings . Split ( strings . TrimSpace ( input ) , " " )
2024-05-10 18:05:03 +00:00
2024-05-10 19:50:55 +00:00
switch len ( tokens ) {
case 0 :
2024-05-10 21:38:20 +00:00
continue EventForLoop
2024-05-10 19:50:55 +00:00
case 1 :
2024-05-11 09:27:05 +00:00
single_float , err1 := strconv . ParseFloat ( tokens [ 0 ] , 64 )
switch {
case tokens [ 0 ] == "i" :
2024-05-10 21:38:20 +00:00
fmt . Printf ( "=> %.1f %.1f\n" , old_low , old_high )
logmean_old , logstd_old := boundsToLogParams ( old_low , old_high )
fmt . Printf ( "=> Lognormal, with logmean: %.1f, logstd: %.1f\n" , logmean_old , logstd_old )
2024-05-10 21:47:34 +00:00
continue EventForLoop
2024-05-11 09:27:05 +00:00
case err1 != nil :
new_low = single_float
new_high = single_float
default :
fmt . Println ( error_msg_cont )
continue EventForLoop
2024-05-10 21:38:20 +00:00
}
2024-05-10 19:50:55 +00:00
case 2 :
new_low , err1 = strconv . ParseFloat ( tokens [ 0 ] , 64 )
new_high , err2 = strconv . ParseFloat ( tokens [ 1 ] , 64 )
2024-05-11 09:27:05 +00:00
if err2 != nil {
2024-05-10 21:38:20 +00:00
fmt . Println ( error_msg_cont )
continue EventForLoop
2024-05-10 19:50:55 +00:00
}
switch tokens [ 0 ] {
case "*" :
2024-05-11 09:27:05 +00:00
new_low = new_high
2024-05-10 19:50:55 +00:00
case "/" :
2024-05-11 09:27:05 +00:00
new_low = 1.0 / new_high
new_high = new_low
default :
if err1 != nil {
2024-05-10 21:38:20 +00:00
fmt . Println ( error_msg_cont )
continue EventForLoop
2024-05-10 19:50:55 +00:00
}
2024-05-11 09:27:05 +00:00
}
case 3 :
new_low , err1 = strconv . ParseFloat ( tokens [ 1 ] , 64 )
new_high , err2 = strconv . ParseFloat ( tokens [ 2 ] , 64 )
if err1 != nil || err2 != nil {
fmt . Println ( error_msg_cont )
continue EventForLoop
}
switch tokens [ 0 ] {
case "*" :
case "/" :
2024-05-10 19:50:55 +00:00
tmp_low := new_low
new_low = 1.0 / new_high
new_high = 1.0 / tmp_low
default :
2024-05-10 21:38:20 +00:00
fmt . Println ( error_msg_cont )
continue EventForLoop
2024-05-10 19:50:55 +00:00
}
2024-05-10 21:38:20 +00:00
default :
fmt . Println ( error_msg_cont )
continue EventForLoop
2024-05-10 19:50:55 +00:00
}
2024-05-11 09:27:05 +00:00
2024-05-10 18:07:58 +00:00
// Use the abstracted function for combining floats
2024-05-10 18:25:23 +00:00
old_low , old_high = combineBounds ( old_low , old_high , new_low , new_high )
fmt . Printf ( "=> %.1f %.1f\n" , old_low , old_high )
2024-05-10 18:05:03 +00:00
}
}