【问题标题】:Printing randomly from a list OCAML从列表中随机打印 OCAML
【发布时间】:2019-11-16 22:32:50
【问题描述】:

如何以随机顺序仅打印文本文件中的每一行一次?

我有一个包含六个单独行的文本文件,我正在尝试将它们随机打印到屏幕上

这是我目前的代码

open Scanf 
open Printf

let id x = x 
let const x = fun _ -> x
let read_line file = fscanf file "%s@\n" id 
let is_eof file = try fscanf file "%0c" (const false) with End_of_file -> true


let _ = 
  let file = open_in "text.txt" in 
  while not (is_eof file) do 
    let s = read_line file in
    printf "%s\n" s 
  done;

  close_in file

我可以将元素“s”附加到列表中。打印列表中的元素可以很简单,但是我不确定如何随机打印列表中的元素。

let rec print_list = function 
[] -> ()
| e::l -> print_int e ; print_string " " ; print_list l

【问题讨论】:

    标签: ocaml


    【解决方案1】:

    使用随机比较器对列表进行排序。例如通过以下函数。

    let mix =
      let random _ _ =
        if Random.bool() then 1 else -1 in
      List.sort random
    

    编辑 1 (15.11.20)

    List.sort 实现Merge Sort 算法。合并排序具有稳定的 O(n log n)。此算法的步数也不依赖于项目比较的结果。这意味着我们的非确定性随机函数不会影响 List.sort 工作的时间。 (下图来自维基百科)

    如果我们的输入数据是列表并且我们不能使用可变数据结构 - 我认为不可能实现比 O(n log n) 更好的 Big O 解决方案,因为列表不可变并且需要随机访问项目.

    【讨论】:

    • 可以 List.sort 以这样的比较标准终止吗?
    • @PierreG。为什么可以呢?对于List.sort,比较器的工作方式没有区别。它实现了 Marge 排序。但我也认为fast_sort 没有问题。
    • 事实上,我不太确定它是否总是有效——尽管我无法证明它;它总是适用于我所做的几个例子。令我困惑的是,当一个列表被排序时,比较函数将返回相同的值,即 1 - 但由于随机函数将返回 -1 或 1,我想知道对于某些列表和一些随机序列是否可能需要很长时间完成时间(极端用例:如果 Random.bool() 不是那么随机并且总是返回 -1 );。可能大部分时间它都有效。就个人而言,我发现你的回答非常聪明——但后来我质疑它的有效性。
    • @PierreG。我理解你。我们无法保证合并排序在使用返回未确定结果的比较函数时具有稳定的 O(n log n)。好的,我研究一下这一点。
    【解决方案2】:

    让我们定义一个函数来检索一个由其在列表中的位置标识的元素,并返回一个元组(this_element, the_list_wo_this_element)。

    Ex : pick [0;2;4;6;8] 3
    returns (6, [0;2;4;8)).
    

    然后,通过迭代结果列表(上面元组的 rhs),从该列表中选择一个随机元素,直到该列表为空。

    【讨论】:

      猜你喜欢
      • 2023-03-03
      • 2020-05-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多