codewars / runner

Issue tracker for Code Runner
34 stars 8 forks source link

Add range-v3 support #42

Closed leira closed 4 years ago

leira commented 6 years ago

The katas on Codewars are really suitable for practicing functional style programming. It will be really nice to include range-v3 (https://github.com/ericniebler/range-v3) for C++ support, to bring up the expressiveness to the same level of other languages.

Urfoex commented 4 years ago

+1 Any news on this one?

kazk commented 4 years ago

No, but I can start looking into it.

Urfoex commented 4 years ago

Can we help in any way? Some pull-request somewhere?

Library on Debian and similar would be: libfmt-dev Flags should just be linking flags:

$ pkg-config --cflags --libs fmt
-lfmt

Checking the docker image: https://hub.docker.com/r/qualified/clang I see you are using some older base version? Ubuntu 18.04.5 LTS (Bionic Beaver) ? With e.g. Debian testing / bullseye (https://hub.docker.com/_/debian?tab=description) you wouldn't need to build some of the libraries and tools yourself, and could just use the given ones, e.g.:

Clang 9.0 https://packages.debian.org/bullseye/clang CMake 3.18.4 https://packages.debian.org/bullseye/cmake Ninja 1.10.1 https://packages.debian.org/bullseye/ninja-build libfmt-dev 6.1.2 https://packages.debian.org/bullseye/libfmt-dev libcriterion-dev 2.3.3 https://packages.debian.org/bullseye/libcriterion-dev librange-v3-dev 0.11.0 https://packages.debian.org/bullseye/librange-v3-dev

But, I have no clue how it would be with Ubuntu 18.04.5 LTS (Bionic Beaver) or newer versions…

kazk commented 4 years ago

Thanks for looking into it.

you wouldn't need to build some of the libraries and tools yourself, and could just use the given ones

Yeah, it'll be nice if we can avoid building them from the source.

For libtbb (#85), I found a link to a .deb file on https://ubuntu.pkgs.org/20.04/ubuntu-universe-amd64/libtbb-dev_2020.1-2_amd64.deb.html and used that.

Maybe

will work.

We can update to a newer base, but that might be a breaking change for a lot of the existing kata and anything installed on the new one won't be usable until kata are updated to be compatible.

I should be able to have some time tomorrow.

kazk commented 4 years ago

Here's the current Dockerfile if you're interested. https://gist.github.com/kazk/47e1c3f8eed7919f06145ce5df647f2a

Urfoex commented 4 years ago

Thanks :+1:

I checked the docker image qualified/clang 8 88d924d96fd5 7 months ago 1.02GB via $ docker history --no-trunc 88d924d96fd5 But die Dockerfile of course is much better and easier to work with :+1:

I'll see how far I'll come with that.

Urfoex commented 4 years ago

Oops, I think I overdid it a little :sweat_smile: https://drive.google.com/file/d/1hsuSWflkRNX-TSUA_mIyY2prF4LwcikY

FROM buildpack-deps:focal

ENV LANG=C.UTF-8

RUN set -ex; \
# Specifying user id because the file owner seems to revert to root if the user has
# the same uid (commonly 1000) as the user on host when userns-remap is enabled.
# https://github.com/moby/moby/issues/39169
    useradd --create-home -u 9999 codewarrior; \
    mkdir -p /workspace; \
    chown -R codewarrior:codewarrior /workspace;

ENV PATH=/opt/cmake/bin:$PATH
RUN set -ex; \
    wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - ;\
    echo "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-11 main" > /etc/apt/sources.list.d/clang-11.list; \
    apt-get update; \
    apt-get install -y --no-install-recommends \
        software-properties-common \
        clang-11 \
        gcc-10 \
        g++-10 \
        ninja-build \
        libtbb-dev \
    ; \
#
# clean up
    apt-get autoremove -y; \
    apt-get clean; \
    rm -rf /var/lib/apt/lists/*;

RUN set -ex; \
# Install newer version of CMake with the official binary release
    mkdir -p /opt/cmake; \
    wget -q -O - https://github.com/Kitware/CMake/releases/download/v3.18.4/cmake-3.18.4-Linux-x86_64.tar.gz | tar xz -C /opt/cmake --strip-components=1; \
    rm -rf /opt/cmake/man /opt/cmake/doc /opt/cmake/bin/cmake-gui; \
#
# Install {fmt}
    cd /tmp; \
    git clone --recursive --depth 1 --branch 7.1.0 https://github.com/fmtlib/fmt.git; \
    mkdir -p fmt/build; \
    cd fmt/build; \
    cmake -GNinja ..; \
    ninja install; \
#
# Install range-v3
    cd /tmp; \
    git clone --recursive --depth 1 --branch 0.11.0 https://github.com/ericniebler/range-v3.git; \
    mkdir -p range-v3/build; \
    cd range-v3/build; \
    cmake -GNinja ..; \
    ninja install; \
#
# Install Criterion
    wget -q -O - https://github.com/Snaipe/Criterion/releases/download/v2.3.3/criterion-v2.3.3-linux-x86_64.tar.bz2 | tar xj -C /usr --strip-components=1; \
#
# Install Igloo
    cd /tmp; \
    git clone --recursive --depth 1 --branch codewars https://github.com/codewars/igloo.git; \
    mkdir -p igloo/build; \
    cd igloo/build; \
    cmake -GNinja ..; \
    ninja install; \
#
# clean up
    rm -rf /tmp/*;

COPY rootfs/opt/runner /opt/runner
RUN set -ex; \
    cd /opt/runner; \
    clang-11 -c criterion-hooks.c -Wall -Wextra;

COPY --chown=codewarrior:codewarrior rootfs/workspace/gtest /workspace/gtest
USER codewarrior
ENV CC=/usr/bin/clang-11 CXX=/usr/bin/clang++-11 LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
RUN set -ex; \
    cd /workspace/gtest; \
    cmake -S . -B build -G Ninja; \
    cmake --build build && ./build/tests/tests; \
    rm -rf ./build/src ./build/tests ./src/lib.cpp ./tests/test_counter.cpp ./include/challenge;

COPY --chown=codewarrior:codewarrior rootfs/testlibraries.cpp /tmp/testlibraries.cpp
RUN set -ex; \
    clang++-11 --std=c++20 -Wall -Wextra -o /tmp/testlibraries /tmp/testlibraries.cpp -ltbb -latomic -lfmt && /tmp/testlibraries; \
    rm -rf /tmp/testlibraries*;

WORKDIR /workspace

testlibraries.cpp

#include <igloo/igloo_alt.h>

#include <fmt/format.h>
#include <range/v3/numeric/accumulate.hpp>
#include <range/v3/to_container.hpp>
#include <range/v3/view/iota.hpp>
#include <range/v3/view/transform.hpp>
#include <range/v3/view/take.hpp>
#include <range/v3/view/take_while.hpp>

#include <algorithm>
#include <execution>
#include <functional>
#include <iostream>
#include <string>
#include <vector>

using namespace std::literals::string_literals;

auto test_fmt() -> void {
    auto const string = fmt::format("{} {}!"s, "Hello"s, "World"s);
    fmt::print("Printing: '{}'\n", string);
}

auto test_range() -> void {
    auto const square = [](uint64_t const n) -> uint64_t {
        return n * n;
    };
    auto const smaller = [](uint64_t const max) -> std::function<auto (uint64_t) -> uint64_t> {
        return [max](uint64_t n) -> bool {
            return n <= max;
        };
    };
    auto const squares = ranges::views::iota(0)
        | ranges::views::transform(square)
        | ranges::views::take_while(smaller(100));
    auto const sum = ranges::accumulate(squares, 0);
    fmt::print("Square Sum = {}\n", sum);
}

auto test_execution() -> void {
    auto const square = [](int64_t const n) -> int64_t {
        return n * n;
    };
    auto const squares = ranges::views::iota(0)
        | ranges::views::transform(square)
        | ranges::views::take(1000)
        | ranges::to<std::vector<int64_t>>();
    auto transformed = std::vector<int64_t>(squares.size());
    std::transform(
        std::execution::par,
        squares.begin(), squares.end(),
        transformed.begin(),
        square
    );
    auto const reduce = [](int64_t const a, int64_t const b) -> int64_t {
        return a + b;
    };
    auto const transform = [](int64_t const n) -> int64_t {
        return std::sqrt(std::sqrt(n));
    };
    auto const res = std::transform_reduce(
        std::execution::par,
        transformed.begin(), transformed.end(),
        static_cast<int64_t>(0),
        reduce,
        transform
    );
    fmt::print("Transformed Sum: {}\n"s, res);
}

auto test_igloo(int argc, char * * argv) -> void {
    igloo::TestRunner::RunAllTests(argc, argv);
}

auto main(int argc, char * * argv) -> int {
    test_fmt();
    test_range();
    test_execution();
    test_igloo(argc, argv);
    return 0;
}
kazk commented 4 years ago

Thanks, but like I wrote above, I was trying to avoid updating to newer base for compatibility reasons.

If we use Focal and a new compiler versions, we should be able to install relatively new fmt and range-v3 from apt without building from source, right? We can add a separate C++20 version and add these packages there.

Also, I got errors trying to use fmt with Igloo's test because of It (see #87).

Urfoex commented 4 years ago

Yeah, totally understandable.

A C++20 Version would be nice. But checking the current support, there are still things missing in the language and the compilers. Also, solving the Katas I didn't have the feeling on missing out and much of C++20 yet. Mostly the ranges and formatting things, that could be done with those here mentioned libraries.

(It would be more the clangd-based editor-auto-completion, that I saw on hackerrank, that would be nice to have here too. Or some other kind of quick/easy integration with a local editor…)

For installing the libraries I didn't find official and new packages for 18.04. But installing them from current releases from souce was no problem with the current Dockerfile you provided.

kazk commented 4 years ago

Yeah, I'd like to wait a little for C++20.

But installing them from current releases from souce was no problem with the current Dockerfile you provided.

You were able to make it work with bionic? The file I got from your Google Drive has FROM buildpack-deps:focal so I assumed you couldn't.

kazk commented 4 years ago

It would be more the clangd-based editor-auto-completion, that I saw on hackerrank, that would be nice to have here too.

I didn't know they had Language Server based autocompletion enabled for simple challenges for any user. It's not working for me for some reason, but I see it's trying to connect to a server over WebSocket.

When there's only a single known file like their simple challenges, it's not that difficult to support because you can spawn Language Servers for each connection and let it work in memory. It gets tricky and expensive (financially) to support multiple files because Language Server will need to read from files that was edited.

Not intended for Codewars (maybe in the future), but I'm working on to support Language Servers on Qualified that supports full projects.

Rust Analyzer with CodeMirror client: image https://github.com/qualified/lsps

Still work in progress, but it supports any Language Server over WebSocket and also in-browser Language Server in Web Workers.

Not many Language Servers can currently run in browser, so I wrote lsp-ws-proxy that allows editor <-> ws <-> stdio communication with any Language Servers. I'm sure HackerRank is doing something similar with clangd. I'm hoping more Language Servers will be able to run in the browser with WASM and some virtual filesystem though. That will allow us to provide this to more users.

Or some other kind of quick/easy integration with a local editor…

Yeah, we have that for Qualified, but nothing for Codewars. I'd like to eventually support it when Codewars have proper APIs.

kazk commented 4 years ago

The file I got from your Google Drive has FROM buildpack-deps:focal so I assumed you couldn't.

Sorry, I missed your comment on the other issue. Thanks!

Urfoex commented 4 years ago

Sorry for the confusion :sweat_smile:

And a big thanks for being so quick and having done the changes :+1:

You are working on some interesting things their. I'll happily see what will come out of it :+1:

kazk commented 4 years ago

Deployed. @Urfoex Thanks again for your help!