koprus77's blog

By koprus77, history, 3 years ago, In English

I just noticed that any of Ruby solutions (even the simplest) have more than 0.45s time.

For example, I have this O(1) solution: 99140692. Or even such simple submission without input at all 99200379 has an execution time bigger than 0.45s.

I understand that Ruby is not the best language for competitive programming and some problems could not be solved in it anyway. But for me, this issue looks like some server misconfiguration and I hope it could be easily solved.

I see this issue is really important for Ruby coders because I believe this is the reason why I had TLE in the last round 99183270

  • Vote: I like it
  • +26
  • Vote: I do not like it

»
3 years ago, # |
  Vote: I like it +19 Vote: I do not like it

Seems like now the situation is somewhat better with Ruby 3 now, because the fastest solutions take around ~250 milliseconds.

As for Ruby being not the best language for competitive programming, this could be eventually solved at some point in the future by getting Crystal compiler available on codeforces platform (but this won't happen fast because Crystal has poor Windows operating system support at the moment). Many simple Ruby programs can be compiled by Crystal with no changes at all and run almost as fast as C++ code.

Though after reading Gassa's excellent blog post, I think that D programming language may serve as a reasonable substitute at least today:

Ruby/Crystal code:

a = [1, 2, 3]
p a
p a.reverse.join(", ")

b = {1 => ["x", "y"], 99 => ["z"]}
p b[1]
p b

c = [1, 2, "x"]
p c

x = 1 << 30
p x
p x * 2

D code:

import std;
void main() {
  auto a = [1, 2, 3];
  writeln(a);
  writeln(a.reverse.map!"to!string(a)".join(", "));

  auto b = [1: ["x", "y"], 99: ["z"]];
  writeln(b[1]);
  writeln(b);

  // auto c = [1, 2, "x"]; // won't even compile

  auto x = 1 << 30;
  writeln(x);
  writeln(x * 2);
}

Both Ruby/Crystal and D can apply a chain of transformations to data. They all can also support debugging prints of even somewhat complicated data structures, such as nested containers in the examples above. This is very useful.

Crystal does arithmetic overflow checks and array bounds checks by default. So x * 2 will trigger a runtime error when running the code compiled by Crystal, while Ruby will print 2147483648 and D will print -2147483648. Such differences do exist and one needs to be careful.

Are there some other programming languages worth considering for Ruby people?

  • »
    »
    3 years ago, # ^ |
      Vote: I like it +8 Vote: I do not like it

    Kotlin is a nice language. Less verbose than Java while supporting everything Java does. There's a good getting started thing here (https://kotlinlang.org/docs/competitive-programming.html), and this is how you'd write that program:

    fun main() {
        val a = listOf(1, 2, 3)
        println(a.joinToString(" "))
        println(a.reversed().joinToString(", "))
    
        val b = mapOf(1 to listOf("x", "y"), 99 to listOf("z"))
        println(b[1])
        println(b)
    
        val c = listOf(1, 2, "x")
        
        val x = 1 shl 30
        println(x)
        println(x * 2)
    }
    
    • »
      »
      »
      3 years ago, # ^ |
        Vote: I like it +11 Vote: I do not like it

      Thanks! I'll give Kotlin a try. Being popular/useful/good for something other than programming competitions is also a big plus.

  • »
    »
    3 years ago, # ^ |
      Vote: I like it 0 Vote: I do not like it

    The line

      writeln(a.reverse.map!"to!string(a)".join(", "));
    

    can be written more concisely as

      writeln(a.retro.map!text.join(", "));
    

    And yeah, lists (arrays) have to contain items of the same type. Though Variant can be used in principle, like this:

      auto c = [Variant(1), Variant(2), Variant("x")];
      writeln(c);
    

    The ability to read-ably express a chain of transformations to data is also present at least in Java (Streams since Java 8) and C# (LINQ since .NET Framework 3.5).