V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  GuuJiang  ›  全部回复第 11 页 / 共 20 页
回复总数  390
1 ... 3  4  5  6  7  8  9  10  11  12 ... 20  
2021-07-24 11:11:55 +08:00
回复了 mrxyz 创建的主题 问与答 想搞一个以 Python 运行的计算骰子结果的程序,求建议。
@mrxyz 这不就是“吹牛”嘛,好好的规则被你给描述得细碎
这个游戏说实话跟概率关系不大,因为别人的任意一次报点都有可能是假的,虽然通过统计确实可以得出一些类似“这个人上一次和这一次之间必有一个是假的”这样的结论,但是对于游戏决策没有关注,因为有可能是上一次假这一次真

@charlie21 @zxCoder 给楼上看不懂规则的解释下,如果没理解错,题主说的应该是流行于全国各地酒吧的名为“吹牛”的游戏,基本规则如下
1. 所有人摇骰子,每个人只能看到自己的点数,按顺序依次行动
2. 每次行动中可以喊“X 个 Y”,意思是所有人的骰子加起来至少有 X 个骰子点数为 Y
3. 上一个玩家喊完后下一个玩家可以接着喊 X1 个 Y1,且必须满足 Y1 > Y or (Y1 == Y and X1 > X),也可以选择开,如果选择了开,所有人把骰子翻开,如果上家喊的条件满足则上家喝酒,否则开的这个玩家喝酒,游戏结束
4. 还有其他一些补充规则,例如 1 可以当任意点,但是如果有人喊过 X 个 1 则此规则失效

这个游戏由于是非完全信息博弈,且有很大的心理成分,所以用程序计算的帮助不大,实战当中基本的技巧一般是利用自己某个点数较多的优势,把对手逼到一个“喊又喊不过,开的话你又是真的”这个境地,同时前期还可以冒险喊一些假的,让别人对你的点数产生误判,从而在后面喊真的进行出击时积累优势,这些更多考验的是心理素质、表演能力以及对对手风格的熟悉程度等,假设对面是个绝对理性的人或机器,在已知大家都只会选择最优解的前提下,可以通过马尔可夫过程大致推断出对面的点数从而做出决策,但要是对面是个不按常理出牌乱喊一气的,理性一方反而会被乱拳打死老师傅,因为你从前面得到的虚假信息中推出了错误的结论
确定 df 是在你目前用的这个 svn 服务器上运行的么?
2021-07-19 21:34:51 +08:00
回复了 Leviathann 创建的主题 问与答 代数效应和代数数据类型里的代数是指的什么?
代数是研究结构的学科,以代数系统为例,给定一个集合,定义若干种运算,就构成了一个代数系统,按照这些运算的性质进一步归类为一些特殊的代数系统,例如群、环、域等等,代数最大的特点就是抽象,虽然学习过程中会先从一些熟悉的具体的例子开始,例如自然数的加法和乘法构成的代数系统等,但是代数系统本身并不局限于具体事物,而是关注抽象的事物之间的联系,用程序来类比的话有点面向接口而非面向实现的这个意思在里面
你题目中说的代数数据类型,因为不清楚上下文,姑且以我自己知道的 haskell 来举例,由于可以给类型定义“加法”、“乘法”等运算,从而可以证明 haskell 的类型构成了一个代数系统,既然构成一个代数系统,那么已知的代数系统里满足的性质类型系统自然也都满足,从而可以推导出一些有趣的结论
2021-07-19 13:04:26 +08:00
回复了 Mexion 创建的主题 问与答 为什么泛型使用了 extends 就不能存东西了?
@Mexion 这个其实是个很有价值的问题,说句冒犯的话,我相信现在越来越多的 Java 程序员当问到他这个话题时,都能说出协变、逆变、PECS 原则等名词,但是继续深入追问下去就会发现开始难以自圆其说了,在这里我根据自己的理解,争取能够一次性把这个问题说清楚
1. 首先回答你主题里的疑问,首先你的疑问来自于一个误解,List<? extends Animal>并不是用来约束里面元素类型的,而是用来约束 List 本身的,只要这个弯转过来那主题里的疑问以及其他类型的疑问都一并迎刃而解了,为什么说这是个误解,有个很简单的证据,你直接写个 List<Animal>,里面一样是可以存 Animal 及其子类的,所以 List<? extends Animal>绝对不是表示这个 list 可以存 Animal 及其子类的意思,到底表示什么下面展开讲
2. 首先简单回顾一点预备知识,在绝大多数的 OO 语言里,类的继承关系都是表示 is-a 的关系,简单地说就是如果 B is-a A,那么在所有期望一个 A 的地方(包括方法参数,变量等),都可以提供一个 B,并且不需要任何的显示类型转换,这就是为什么可以写 List l = new ArrayList();的原因,对于简单类型,判断 is-a 很简单,只要二者在一条继承关系的链上,就能定义 is-a 关系,但是引入泛型后,问题就开始变得有点复杂了,List<Animal>和 List<Dog>之间的 is-a 关系是怎么样的呢?结论是不具有 is-a 关系,List<Animal> is-a List<Dog>不成立看起来是显然的,但是反过来似乎就有点反直觉了,这就涉及到下面要讲的几个概念
3. 关于不变(invariant)、协变(covariant)、逆变(contravariant),首先声明,虽然这里使用 Java 语言举例,但是这几个概念在几乎所有支持泛型的 OO 语言里都存在,事实上这几个概念在存在计算机语言之前就已经存在了,是范畴论里的几个概念,下面以 Java 为例说下分别是什么意思,前面说了,List<Animal>和 List<Dog>之间不存在 is-a 关系,这就叫做不变(invariant),但是有的时候,我们需要让它们之间存在 is-a 关系,这就要通过一些关键字来人为指定下面两种关系,假设规定 List<Dog> is-a List<Animal>,这种关系就叫做协变(covariant),因为 List 之间的 is-a 关系和 Animal 及 Dog 之间的 is-a 关系方向是一致的,反之,如果规定 List<Animal> is-a List<Dog>,这种关系就叫做逆变(contravariant),因为 List 之间的 is-a 关系和 Animal 及 Dog 之间的 is-a 关系方向是相反的,各种语言里都会有一些标识来定义协变及逆变,例如 c#用 in/out,scala 用+/-,而 Java 就是用的 extends 和 super,简单说 List<? extends Animal>实际表示的是,对于这个变量,可以接受 List<Animal>,也可以接受 List<Dog>、List<Cat>等,反之,如果定义 List<? super Animal>,那么表示这个变量可以接受 List<Animal>、List<Object>等,这就是我在开头说的,当定义一个变量 List<? extends Animal> l 时,这里的 extends 并不是约束“l 里可以存什么”,而是约束“什么样的 List 能够赋值给 l”
4. 相信到这里题主应该已经能够自己想通问题出在哪了,但是我还是顺便展开说一说 PECS 原则,PECS 原则确实是个帮助记忆的好东西,但是真正合格的程序员应该主动多思考一下,PECS 里是用 List 举例的,但是泛型类并不一定都是个容器,对于非容器类型的泛型类,到底什么算 produce 什么算 consume,其实,所谓的 produce 和 consume 是人逻辑上的概念,编译器肯定不认识啊,所以 PECS 的本质其实指的是这个类型边界出现在方法参数上还是出现在返回值里,下面举个例子,假如我们写了一个方法,作用是将一个 list 里的元素取出来进行某种操作然后放到另一个 list 里,为什么方法签名必须定义成这个样子
void map(List<? extends Animal> source, List<? super Animal> target)
首先,对于 source,我们可能会进行这样的操作
Animal a = source.get(0);
这就要求传给 source 的 list 必须满足“能够从中取出 Animal”这个条件(当然,从编译器的角度,应该是“可以调用返回类型为 Animal 的方法”),因此当在调用 map 时,可以给 source 参数传 List<Animal>、List<Dog>、List<Cat>都是合法的,但是不能传 List<Object>
而对于参数 target,我们可能进行这样的操作
target.add(a);
这就要求传给 target 的 list 必须满足“能够往里添加 Animal”这个条件(当然,从编译器的角度,应该是“可以调用参数为 Animal 的方法”),因此当在调用 map 时,可以给 target 参数传 List<Animal>,List<Object>都是合法的,假设 target 能够接受 List<Dog>,而在 map 方法体内部往里放了个 Animal,这显然是不合理的

一不小心写了这么多,最后放个太长不看版吧,一句话,对于 List<? extends Animal> l 和 List<? super Animal>,泛型边界并不是表示 l 里能够存什么,而是表示 l 能够接受什么样的 list
2021-07-17 13:53:13 +08:00
回复了 RedBlackTree 创建的主题 程序员 请教大家一个关于栈空间的问题
@RedBlackTree

用“创建”变量这个词容易让人产生一种误解,好像变量是某种资源一样,“创建”是个消耗资源的过程,实际上所有的局部变量仅仅是 BP+N 这个地址的一个代号而已,并且这个 N 在编译时已经确定了,换句话说在运行时根本就没有所谓的“创建”变量这回事,跟是否循环没有任何关系
2021-07-16 20:26:10 +08:00
回复了 zxCoder 创建的主题 English 我们常说的业务代码 业务逻辑,用英语咋说?
business logic
2021-06-29 11:47:48 +08:00
回复了 wjg8850 创建的主题 English target garget 中的 get 读 git,forget beget 中的 get 读 get.为什么呢...
重读音节和非重读音节
@0576coder 是的,你在主题中的疑惑应该来自于“反正都要手写 Class.forName,那么 spi 就没意义了”,事实上只要认识到 Class.forName 不但是多余的,甚至根本就是错误的,正确的做法是只需要把带有元信息的相应的实现放到 classpath 即可,当需要替换驱动时对代码完全无感,从这个角度看 spi 跟多态、DI 、服务发现等都是一回事,手写 Class.forName 反而依赖了具体实现
Class.forName 是在用了 SPI 机制之前的加载技术,实际上当包加入了 SPI 元信息后并不需要再写 Class.forName 了,只不过天下文章一大抄,各种只知其然不知其所以然的“教程”仍然在把 Class.forName 这种已经过时的东西传来传去
2021-06-28 22:44:16 +08:00
回复了 movq 创建的主题 程序员 Java 里面 import 时星号*的意义是什么
因为你并没有 com.example 这个包,你有的只是 com.example.model 和 com.example.web 这两个包,*只能匹配 class 等,不能匹配(实际上也并不存在) subpackage
2021-06-28 13:21:41 +08:00
回复了 fly2mars 创建的主题 问与答 如何声明一个需要位运算的变量? 比如 x & 1 = 1,int x = ??
@fly2mars 虽然你一直没表达清楚,但是可以隐约猜测出来你想要实现的就是要把“满足某种条件的全体元素”这个抽象概念变成一个具体的概念,可以赋值给变量,可以作为参数传递,可以作为返回值返回,这种“把抽象的东西当成具体的东西来传递”的通用做法是使用高阶函数,当然这里我不打算提,否则你会更晕的,具体到你这个例子里,你只需要使用
int x = 1 来表示“全体满足(x&1)!=0 的数”
int x = 2 来表示“全体满足(x&2)!=0 的数”
...
即可,只不过在凡是用到这个变量的地方都要牢记它表示的其实不是一个数而是一个集合,对它能做的运算也只有有限的几种,在只关系集合这个整体的地方,就原样传递这个变量即可,等到了真正需要列举出元素或者测试某个值是否属于这个集合的地方,再使用运算(x&a)!=0
2021-06-28 13:09:27 +08:00
回复了 fly2mars 创建的主题 问与答 如何声明一个需要位运算的变量? 比如 x & 1 = 1,int x = ??
@fly2mars 我觉得你一定是在某个地方存在某种误解
举个例子,x^2=1(此处是指平方而不是异或),那么 x 到底是 1 还是-1
数学上要表达一个函数,既可以用显函数方式 y=f(x),也可以用隐函数方式 F(x, y)=0
诚然,对于单值的情况确实显函数看起来更符合直觉一点,因为人们习惯于“xx 是 xx”这种表达方式,但是对于多值的方式有的时候只能用隐函数(这里对隐函数概念做了推广,严格来说多值的不应该称为函数)
更哲学一点,定义一个东西既可以用内涵定义(某某是什么),也可以用外延定义(满足什么条件的是某某)
你想要的是满足(x&1) != 0 的全体整数,并且试图用一个值来表达这个集合,如果硬要表示出来,那么 x 一定不是一个数而是一个集合{1, 3, 5, 7, 9, ...}在这个场景之下,没有比 1 能更简洁的表达这个集合的方式了,推广一下,用 a 来表达全体满足(x&a)!=0 的整数,或者更形式化点,有个带参函数
F(x,t) => (x & t) != 0
那么每个 t 都表示了一个集合,换言之,你本身已经有了简洁的表达集合的方式,但是试图去找一种更“简洁”的表示方式,本末倒置了
2021-06-28 12:40:50 +08:00
回复了 fly2mars 创建的主题 问与答 如何声明一个需要位运算的变量? 比如 x & 1 = 1,int x = ??
@fly2mars 你要的这个不就是普通的 flag 的组合吗?在你举的这个例子里就是
int x = 1;
2021-06-28 12:19:57 +08:00
回复了 fly2mars 创建的主题 问与答 如何声明一个需要位运算的变量? 比如 x & 1 = 1,int x = ??
直接说你的原始需求吧,不要再在 XY 问题上浪费时间
2021-06-17 16:21:22 +08:00
回复了 rationa1cuzz 创建的主题 问与答 一道需求引发的数学题
71
“每位老师最多评审 50 支团队”这个条件可以等价为每个老师手底下有 50 个苦逼研究生,当需要老师去评审的时候其实是派一个研究生去当枪手,且每个枪手只能用一次,为了结果最大化,采用贪心策略,每当需要一轮评审的时候从剩余研究生数最多的老师里选 7 个成团,于是问题进一步简化为了在一个 10*50 的矩阵里从左到右依次取 7 个元素,不够 7 个时折行,最多能取几次,最终简化成了 500/7
@xuanbg 要不你再好好想想?匹配的是子串,不是子序列
这其实是一个非常有意思的问题,不知道真实的密码锁是怎么实现的,但是假如让我来设计一个密码锁的话,我会采用下面的方案
当设置密码时,将设置的密码编译为一个 AC 自动机(当然由于只有一个关键词,所以实际退化成了 KMP,不过也可以支持多密码),这样每按一个键时实际是在自动机中进行转移,当到达终结状态时就开门,这有个巨大的好处,无论前面输入的无效内容有多长,都不会带来时间和空间上的额外开销,理论上可以支持的无效内容长度没有上限
假设密码锁真的采用了这样的方案,那么确实可以认为是明文存储的,虽然没有直接地存储密码本身,但是获得了完整的自动机等价于获得了密码,不过对于密码锁这种必需要物理接触才能使用的系统来说,直接暴力破坏恐怕都比试图读取存储要容易得多,所以是否明文存储已经不是那么重要了
那要不试试你们心目中的产品之神 telegram 呗?家里的老人,不会发文字,微信只拿来视频用,是直接点击任意一次通话的气泡方便还是选择菜单-“视频通话”方便?至少我用过的 IM 全都是这个逻辑
虽说在 v 站黑张小龙才是政治正确,但这个功能真的没什么黑点吧?系统通讯录的通话记录不也是一样的逻辑?对于一些经常视频很少发文字的联系人来说反而很方便
1 ... 3  4  5  6  7  8  9  10  11  12 ... 20  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   985 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 25ms · UTC 21:08 · PVG 05:08 · LAX 13:08 · JFK 16:08
Developed with CodeLauncher
♥ Do have faith in what you're doing.