Temperatures puzzle discussion

I struggle with getting a BASH version work (I am completely incompetent in bash).
In the main loop I try to get abs value by this:
t=${myArray[$((i))]}
ta=${t#-}
tc=${closest#-}
Then trying to check if a new best solution found by this:
if [ $ta -lt $tc ] || [ [ $ta -eq $tc ] && [ $t -ge 0 ] ]
then
closest=$t
fi;
However the if statement is invalid. How to put it right? Thanks.

okay, just a little web search solved it for me: replacing [ ]and -gt with the (( )) syntax.
if (( ( $ta < $tc ) || ( ( $ta == $tc ) && ( $t >= 0 ) ) ))

If you go for double-parenthesis syntax, you don’t need the dollar signs anymore.

Single-bracket syntax is IMHO to be avoided completely, but there’s little reason you shoudn’t have found any luck with double brackets. What was the actual problem with your statement?

It was syntax error

if [ $ta -lt $tc ] || [ [ $ta -eq $tc ] && [ $t -ge 0 ] ]

Single-bracket conditionals are a builtin in bash, but they strive to maintain compatibility with old-style conditionals using external command test. As such:

  • they don’t nest (at least, not directly)
  • they need a lot of escaping

Making your example to pass would need one of these:

  • closest to your example: [ $ta -lt $tc ] || [ \( $ta -eq $tc \) -a \( $t -ge 0 \) ]
    Notice how the inner tests use parentheses, and they have to be escaped to be interpreted by [ not bash. (they’re actually not needed, it’s just to stick to your template)
  • && and || have equal precedence in bash, and have a behavior equivalent to left-associative short-circuit, so in this case you actually don’t need any parentheses:
    [ $ta -lt $tc ] || [ $ta -eq $tc ] && [ $t -ge 0 ]
  • or in a single expression:
    test \( $ta -lt $tc \) -o \( \( $ta -eq $tc \) -a \( $t -ge 0 \) \)
    that simplifies to:
    test $ta -lt $tc -o $ta -eq $tc -a $t -ge 0

It happens to be ok here because the parameters are defined and non-zero-length, but so many things can go wrong when passing arguments from bash to test that it’s best practice to just always quote variables: "$t".

All of this has been obsolete for years: if you have [[ (you do), use it instead of [.

1 Like

Thanks! By a single post you at least tripled my bash knowledge
 :slight_smile:
It seems bash is a competent tool in the skilled hands, but that is definitely not mine
 My only remaining ambition with bash is to
 reach Legend in the next contest with it
 ehm
correction
 to cash in an extra achievement plus a hefty 25 XPs in the ‘Horse racing’ duals easy training puzzle.

I am not sure if the provided input parser skeleton for OCaml is correct:

(* Auto-generated code below aims at helping you parse )
(
the standard input according to the problem statement. )
let n = int_of_string (input_line stdin) in (
the number of temperatures to analyse )
let line = input_line stdin in
for i = 0 to n - 1 do
(
t: a temperature expressed as an integer ranging from -273 to 5526 )
let t = Scanf.sscanf line “%d” (fun t -> (t)) in
();
done;
(
Write an action using print_endline )
(
To debug: prerr_endline “Debug message”; *)
print_endline “result”;

If I add only this line after the “let t” line, it always prints always prints the same first number from the input line:
prerr_endline(string_of_int t);

OCaml gurus: what do i miss?

The parser is indeed incorrect (sscanf always reads the first integer of the line).
Use something like that instead:

let n = int_of_string (input_line stdin) in
let temperatures = List.map int_of_string (String.split_on_char ' ' (input_line stdin)) in
List.iter (fun t -> prerr_endline (string_of_int t)) temperatures

Or alternatively (closer to the provided parser), replace sscanf by scanf (note the space in the format string to eat all whitespaces).

let n = int_of_string (input_line stdin) in
for i = 0 to n - 1 do
    let t = Scanf.scanf " %d" (fun t -> t) in
    prerr_endline (string_of_int t);
done;

Thanks, that solved it.

Bonjour,
c’est pas trĂšs propre ce que j’ai Ă©crit , mais en testant mon code dans jsfiddle.net , j’obtient les bons rĂ©sultats mais ça ne fonctionne pas sur codingame

Is that the same as writing an except block for a different error? Im still learnig code so not sure.

It’s difficult to help you if you don’t tell us what’s not working for you. :wink:

What have you tested? What is blocking you?

Bonjour, j’ai un probleme avec les tests, le 4 eme test ne marche pas. c’est le cas de quelqu’un ici?

dans le 4 eme test il me sort 42 > 5 ‘false’ ?? alors que c’est ‘true’ c’est que ce test qui block.
Merci pour votre aide

All tests are correct 
 It is an historical puzzle solved by 138776 person.

Without knowing your code, hard to say what the problem is.
But 42 > 5 is false if your values are strings. Maybe your variables have wrong datatype.

2 Likes

thank’s for reply, you are right the problem is datatype, i resolved it yesterday :wink::+1:

Bonjour, mĂȘme problĂšme pour moi, tout est dans le vert mais le test 3 n’est pas validĂ© pour le succĂšs.

how does your code behave when there is only 1 temperature given (5526)?

I have been getting this error in Python when testing the first case:

ValueError: invalid literal for int() with base 10: ‘1 -2 -8 4 5’
at Answer.py. in <module> on line 16

It is showing the error is in the line of code that I added to make this:
num = int(input())

This line of code was added because I was making an array in a for loop to input values from the user. What is the issue?

The issue is that input() read the line 

num = int(input()) => num = int('1 -2 -8 4 5')
It is not correct 


What you can do is getting the values as string
nums = input().split()
then you can loop to use these but the base code generated by CG already do this for you :
for i in input().split():

No need to reinvent the wheel :wink:

1 Like