49
[-] sebastiancarlos@lemmy.sdf.org 3 points 2 days ago* (last edited 2 days ago)
78
submitted 3 days ago* (last edited 3 days ago) by sebastiancarlos@lemmy.sdf.org to c/programmerhumor@lemmy.ml

The mystery is finally solved! Yes, the code works.

#!/usr/bin/env swipl --quiet

:- use_module(library(clpfd)).

% ORIGINAL LYRICS:
% Looking for
% Girls who want boys
% Who like boys to be girls
% Who do boys like they're girls
% Who do girls like they're boys
% Always should be someone you really love
%    - "Girls and Boys," Blur, 1994

% DSL CONVERSION:
% girls who like boys
% who like boys (who are girls)
% who like boys (who get done like they're girls)
% who like girls (who get done like they're boys)

% TREE STRUCTURE:
% group(female, none, none, group(
%   male, female, none, group(
%     male, none, female, group(
%       female, none, male, none)))).

% USAGE:
% 1. Get all possible lyrics up to a max depth:
%    ?- group_maxdepth(G, 4), group_string(G, S).
% 2. Get the tree structure of some lyrics (pass a max depth to avoid unbounded recursion):
%    ?- group_maxdepth(G, 4), group_string(G, 'boys who like girls').
% 3. Get the lyrics from a tree structure:
%    ?- group_string(group(male, none, none, group(female, none, none, none)), S).
% 4. Fill in the blanks with all possibilities:
%    ?- group_depth(G, 3),
%       phrase(group_sentence(G), Tokens),
%       append([[girls, who, like], X, [who, like], Y], Tokens),
%       atomic_list_concat(Tokens, ' ', S).

% Genders
gender(male).
gender(female).

% gender_altgender(G, G2)
% Valid relation between gender and alternative genders (isGender and
% PerformGender) in the same group.
gender_altgender(G, none) :-
  gender(G).
gender_altgender(G, G2) :-
  gender(G),
  gender(G2),
  dif(G, G2).

% Group(Gender, IsGender, PerformGender, LikeGroup).
% All arguments but Gender are optional.
% Represents a demographic that can like and can be a target of liking.
group(Gender, IsGender, PerformGender, none) :-
  gender(Gender),
  gender_altgender(Gender, IsGender),
  gender_altgender(Gender, PerformGender).
group(Gender, IsGender, PerformGender, group(Gender2, IsGender2, PerformGender2, Group)) :-
  group(Gender, IsGender, PerformGender, none),
  group(Gender2, IsGender2, PerformGender2, Group).

% DCG to produce a phrase from a group.
% Example:
% ?- phrase(group_sentence(group(male, none, none, group(female, none, none, group(male, none, none, group(male))))), Tokens).
% Tokens = [boys, who, like, girls, who, like, boys, who, like, boys].
group_sentence(group(Gender, IsGender, PerformGender, none)) -->
  { group(Gender, IsGender, PerformGender, none) },
  gender_phrase(Gender),
  group_info_phrase(IsGender, PerformGender).
group_sentence(group(Gender, IsGender, PerformGender, Group)) -->
  { dif(Group, none) },
  group_sentence(group(Gender, IsGender, PerformGender, none)),
  [who, like],
  group_sentence(Group).

gender_phrase(male)   --> [boys].
gender_phrase(female) --> [girls].

isgender_phrase(none) --> [].
isgender_phrase(Gender) --> [are], gender_phrase(Gender).

performgender_phrase(none) --> [].
performgender_phrase(Gender) --> [get, done, like, 'they''re'], gender_phrase(Gender).

% Render isGender and PerformGender within parentheses.
group_info_phrase(none, none) --> [].
group_info_phrase(IsGender, none) --> 
  { dif(IsGender, none) },
  ['(', who], isgender_phrase(IsGender), [')'].
group_info_phrase(none, PerformGender) --> 
  { dif(PerformGender, none) },
  ['(', who], performgender_phrase(PerformGender), [')'].
group_info_phrase(IsGender, PerformGender) --> 
  { dif(IsGender, none), dif(PerformGender, none) },
  ['(', who], isgender_phrase(IsGender), ['and'], performgender_phrase(PerformGender), [')'].

% Relate group and string representation
% ?- group_string(group(male, none, none, group(female, none, none, group(male, none, none, group(male)))), S).
% S = 'boys who like girls who like boys who like boys'
group_string(group(Gender, IsGender, PerformGender, Group), String) :-
  phrase(group_sentence(group(Gender, IsGender, PerformGender, Group)), Tokens),
  atomic_list_concat(Tokens, ' ', String).

% Relate group and depth
%   - group(G0, IG, PG, none) has depth 0
%   - group(G0, IG, PG, group(...)) has depth 1
group_depth(group(Gender, IsGender, PerformGender, none), 0) :-
  group(Gender, IsGender, PerformGender, none).
group_depth(group(Gender, IsGender, PerformGender, Group), Depth) :-
  Depth #> 0,
  group(Gender, IsGender, PerformGender, none),
  Depth0 #= Depth - 1,
  group_depth(Group, Depth0).

% Relate group and all integers larger than its depth.
group_maxdepth(Group, MaxDepth) :-
  MaxDepth #>= Depth,
  Depth #>= 0,
  group_depth(Group, Depth).

43

something is a person if it is either Adam or Eve, or if it has a mother. We can express this in a single rule as follows:

person(X) :- (X=adam; X=eve; mother(X, Y)).

240

Hey everyone,

So, I was doing some last-minute Christmas shopping and thought I scored a deal on a Nintendo Switch for my nephew. Turns out, I didn’t read the description carefully enough, and I ended up with a NETGEAR 16-Port Gigabit Ethernet Managed Switch.

To be fair, it does look like a futuristic game console.

After some initial panic, I’ve decided to just keep it. Who knows? Maybe one day I’ll pivot into the hotel business and need to save on network infrastructure costs. Gotta think long-term, right?

68
submitted 2 weeks ago* (last edited 2 weeks ago) by sebastiancarlos@lemmy.sdf.org to c/programmerhumor@lemmy.ml
% Piano Axioms

% Axiom 1: Law of Excluded Gray
key_type(white).
key_type(black).

% Axiom 2: The C Postulate
key_color(c, white).

% Axiom 3: The Diatonic Scale
next_white_key(c, d).
next_white_key(d, e).
next_white_key(e, f).
next_white_key(f, g).
next_white_key(g, a).
next_white_key(a, b).
next_white_key(b, c).

% Axiom 4: The Semitone Anomaly
semitone_gap(e, f, 1).
semitone_gap(b, c, 1).
semitone_gap(X, Y, 2) :- 
    next_white_key(X, Y),
    X \= e,
    X \= b.

% Axiom 5: Black Key Entropy
has_black_key_between(X, Y) :-
    next_white_key(X, Y),
    semitone_gap(X, Y, 2).

% Axiom 6: The "8 is 12" Principle.
octave_size(12).

% Axiom 7: Out of Bounds Exception
total_keys(88).

% Theorem 1: Conservation of "Wrong Notes"
style(jazz) :-
    wrong_notes > 0,
    write('All wrong notes are now intentional').
166
submitted 2 weeks ago* (last edited 2 weeks ago) by sebastiancarlos@lemmy.sdf.org to c/programmerhumor@lemmy.ml

How to write a programming novel?

  • Cover: CSS
  • Copyright Page: GNU GPLv3
  • Intentionally Blank Page: Whitespace
  • Notes For The Second Edition: Kotlin
  • Notes for The First Edition: Java
  • Front Matter: Markdown
  • Dedication: Rust
  • Prologue: Prolog
  • Chapter 1: C
  • Chapter 2: C++
  • Chapter 3: C3
  • Chapter 4: Forth
  • Pull Quotes: Git
  • Unexpected Sex Scene: LaTeX
  • Dream Sequence: APL
  • Cliffhanger Ending: Python 2
  • Index: IndexedDB
  • Errata: PHP
  • Sequel: SQL
157
class BaseFunction {
  static #allowInstantiation = false;

  constructor(...args) {
    if (!BaseFunction.#allowInstantiation) {
      throw new Error(
        "Why are you trying to use 'new'? Classes are so 2015! Use our fancy 'run' method instead!"
      );
    }
    for (const [name, validator] of this.parameters()) {
      this[name] = validator(args.shift());
    }
  }

  parameters() {
    return [];
  }

  body() {
    return undefined;
  }

  static run(...args) {
    BaseFunction.#allowInstantiation = true;
    const instance = new this(...args);
    BaseFunction.#allowInstantiation = false;
    return instance.body();
  }
}

class Add extends BaseFunction {
  parameters() {
    return [
      ["a", (x) => Number(x)],
      ["b", (x) => Number(x)],
    ];
  }

  body() {
    return this.a + this.b;
  }
}

console.log(Add.run(5, 3)); // 8



12
Makefiles For Threesomes (sebastiancarlos.com)
[-] sebastiancarlos@lemmy.sdf.org 11 points 3 months ago

It's Exclidraw (dark mode)

[-] sebastiancarlos@lemmy.sdf.org 18 points 3 months ago* (last edited 3 months ago)

Totally understand your perspective, and I’m not here to push back against it. You’ve got a valid point.

I’ll just add that there are already commercial tools that do similar things to what I’m building. It’s interesting to consider how perceptions might shift if a tool were released by a company rather than a solo developer. Sometimes the context influences how a tool is interpreted, even if the underlying functionality remains the same. For what it’s worth, I have no commercial intent behind this.

[-] sebastiancarlos@lemmy.sdf.org 21 points 3 months ago

Hey, thanks for the comment. I get that it might be used for something shady, but that’s not the intention. The primary goal is to clean up raw time-tracking data into a format that’s easy to present to clients or supervisors, especially for contexts when small gaps or irregularities should be absent.

I imagine most professionals aren’t expected to account for every single minute of their workday. For example, if you’re switching tasks or taking short breaks. It’s more about reporting general productivity or overall progression of tasks, not trying to inflate hours.

Anyone aiming for 'time fraud' could probably find easier methods. My focus is to make life easier for people who already track their work but want cleaner, more digestible reports.

Appreciate the feedback though, helps me make sure the use case is clear! :)

228

It's almost done (it would take one or two weeks to clean it up for FOSS release). It's a CLI tool. It works great for my use case, but I'm wondering if there's any interest in a tool like this.

Say you have a simple time-tracking tool that tracks what you do daily. The only problem is that there are gaps and whatnot, which might not look nice if you need to send it to someone else. This tool fixes pretty much all of that.

Main format is a JSON with a "description", and either "duration" or a "start"/"end" pair. It supports the Timewarrior format out of the box (CLI Time tracking tool).

-29
165
126
submitted 5 months ago* (last edited 5 months ago) by sebastiancarlos@lemmy.sdf.org to c/linux@lemmy.ml

Either self-hosted or cloud, I assume many of you keep a server around for personal things. And I'm curious about the cool stuff you've got running on your personal servers.

What services do you host? Any unique stuff? Do you interact with it through ssh, termux, web server?

[-] sebastiancarlos@lemmy.sdf.org 12 points 8 months ago* (last edited 8 months ago)

Tbh these scripts are for my personal use, written in the way that makes sense for me. I only open sourced it as a joke an as an example of how reinventing your own wheel is not that hard sometimes, and comes with the benefit of doing just what you need it to do.

Actually I was thinking of adding a sysget fallback, as I might need to do some debian/fedora hacking soon.

[-] sebastiancarlos@lemmy.sdf.org 12 points 1 year ago

Just curious, what would be a correct translation?

[-] sebastiancarlos@lemmy.sdf.org 65 points 1 year ago

The joke is that it's hard to tell if this is a joke because the lines between good intentions, corporate jargon, and feasibility have been blurred beyond recognition both here and in the real world.

It's also funny that after all these years, i18n is still a mess. Moreover, even if translations are standard in GUIs and documentation, for some reason, everyone is okay with defaulting to English for the oldest form of computer interaction.

Also, the joke is whatever you want it to be. Follow your dreams.

[-] sebastiancarlos@lemmy.sdf.org 25 points 1 year ago

It's also traditional to eat raw meat, but we discovered fire at some point.

[-] sebastiancarlos@lemmy.sdf.org 30 points 1 year ago* (last edited 1 year ago)

You also don’t need the dash for the short options.

True, but I refuse to entertain such a non-standard option format. It's already enough to tolerate find's.

[-] sebastiancarlos@lemmy.sdf.org 15 points 1 year ago

it's surely one of the CSS lines of all time

view more: next ›

sebastiancarlos

joined 2 years ago